[#44] socket-REPL: fix problem with EOF

This commit is contained in:
Michiel Borkent 2019-09-01 21:13:37 +02:00 committed by GitHub
parent 790f0d4dba
commit 4a485d51a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 41 deletions

2
sci

@ -1 +1 @@
Subproject commit 225dfe2314f2789b3050be2a70f10c123c13d277
Subproject commit ade0d29a4d3d97d9d6c958434368d5fa4359debf

View file

@ -106,10 +106,7 @@
read-eval-print
(fn []
(try
(let [input (try
(read request-prompt request-exit)
(catch LispReader$ReaderException e
(throw (ex-info nil {:clojure.error/phase :read-source} e))))]
(let [input (read request-prompt request-exit)]
(or (#{request-prompt request-exit} input)
(let [value (eval input)]
(set! *3 *2)

View file

@ -1,43 +1,46 @@
(ns babashka.impl.socket-repl
{:no-doc true}
(:require [babashka.impl.clojure.core.server :as server]
[babashka.impl.clojure.main :as m]
[sci.core :refer [eval-string]]
[sci.impl.parser :as parser]
[sci.impl.toolsreader.v1v3v2.clojure.tools.reader.reader-types :as r]
[clojure.string :as str]
[clojure.java.io :as io]))
(:require
[babashka.impl.clojure.core.server :as server]
[babashka.impl.clojure.main :as m]
[clojure.java.io :as io]
[clojure.string :as str]
[sci.core :refer [eval-string]]
[sci.impl.parser :as parser]
[sci.impl.toolsreader.v1v3v2.clojure.tools.reader.reader-types :as r]))
(set! *warn-on-reflection* true)
(defn repl
"REPL with predefined hooks for attachable socket server."
[sci-opts]
(m/repl
:init #(do (println "Babashka"
(str "v" (str/trim (slurp (io/resource "BABASHKA_VERSION"))))
"REPL.")
(println "Use :repl/quit or :repl/exit to quit the REPL.")
(println "Clojure rocks, Bash reaches.")
(println))
:read (fn [request-prompt request-exit]
(let [in (r/indexing-push-back-reader (r/push-back-reader *in*))
p (r/peek-char in)]
(if (= \newline p)
(do (r/read-char in) request-prompt)
(let [in (r/indexing-push-back-reader (r/push-back-reader *in*))]
(m/repl
:init #(do (println "Babashka"
(str "v" (str/trim (slurp (io/resource "BABASHKA_VERSION"))))
"REPL.")
(println "Use :repl/quit or :repl/exit to quit the REPL.")
(println "Clojure rocks, Bash reaches.")
(println))
:read (fn [_request-prompt request-exit]
(if (r/peek-char in) ;; if this is nil, we reached EOF
(let [v (parser/parse-next {} in)]
(if (or (identical? :repl/quit v)
(identical? :repl/exit v))
(identical? :repl/exit v)
(identical? :sci.impl.parser/eof v))
request-exit
v)))))
:eval (fn [expr]
(eval-string (str expr)
(update sci-opts
:bindings
merge {'*1 *1
'*2 *2
'*3 *3
'*e *e})))))
v))
request-exit))
:eval (fn [expr]
(let [ret (eval-string (pr-str expr)
(update sci-opts
:bindings
merge {'*1 *1
'*2 *2
'*3 *3
'*e *e}))]
ret))
:need-prompt (fn [] true))))
(defn start-repl! [host+port sci-opts]
(let [parts (str/split host+port #":")
@ -60,7 +63,6 @@
(comment
(def sock (start-repl! "0.0.0.0:1666" {:env (atom {})}))
(.accept sock)
@#'server/servers
(stop-repl!)
)

View file

@ -4,17 +4,31 @@
[babashka.test-utils :as tu]
[clojure.java.shell :refer [sh]]
[clojure.string :as str]
[clojure.test :as t :refer [deftest is]]))
[clojure.test :as t :refer [deftest is testing]]))
(def mac?
(str/includes?
(str/lower-case (System/getProperty "os.name"))
"mac"))
(deftest socket-repl-test
(when tu/jvm?
(start-repl! "0.0.0.0:1666" {:env (atom {})})
(is (str/includes? (:out (sh "bash" "-c"
"echo \"(+ 1 2 3)\n:repl/exit\" | nc 127.0.0.1 1666"))
"bb=> 6"))
(stop-repl!)))
(try
(start-repl! "0.0.0.0:1666" {:env (atom {})})
(is (str/includes? (:out (sh "bash" "-c"
"echo \"(+ 1 2 3)\n:repl/exit\" | nc 127.0.0.1 1666"))
"bb=> 6"))
(testing "ctrl-d exits normally, doesn't print nil"
(is (str/ends-with? (:out (sh "bash" "-c"
(if mac? ;; mac doesn't support -q
"echo \"(inc 1336)\" | nc 127.0.0.1 1666"
"echo \"(inc 1336)\" | nc -q 1 127.0.0.1 1666")))
"1337\nbb=> ")))
(finally
(stop-repl!)))))
;;;; Scratch
(comment
(socket-repl-test)
)