diff options
author | scgilardi <scgilardi@gmail.com> | 2008-12-27 23:45:10 +0000 |
---|---|---|
committer | scgilardi <scgilardi@gmail.com> | 2008-12-27 23:45:10 +0000 |
commit | 250b45c739235f30b134c5f613f8d705b7214a0e (patch) | |
tree | 552272ae4a2d29beae63edf9f10fe3a8a2a0ea89 | |
parent | b58849f2a1e2de5114bc46f0e42695f6605cb4c9 (diff) |
revert accidental checkin of repl_ln.clj
-rw-r--r-- | src/clojure/contrib/repl_ln.clj | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/src/clojure/contrib/repl_ln.clj b/src/clojure/contrib/repl_ln.clj index 372eb3ff..7e72a836 100644 --- a/src/clojure/contrib/repl_ln.clj +++ b/src/clojure/contrib/repl_ln.clj @@ -54,6 +54,14 @@ :depth 0) "Default/root values for repl info") +(defvar- +special-character+ + { (int \return) :eol + (int \newline) :eol + (int \,) :ws + (int \;) :cte + -1 :eos } + "Maps interesting character codes to keywords representing their type") + (defonce- *serial-number* (atom 0) "Serial number counter") @@ -76,11 +84,65 @@ {:keys [serial thread depth]} *info*] (format name-fmt serial thread depth))) -(defn- prompt-hook - [] - (let [prompt (*private* :prompt)] - (var-set Compiler/LINE (.getLineNumber *in*)) - (prompt))) +(defn- next-char + "Reads the next character in s and either returns it or one of the + following keywords if the character is of the corresponding type: + :ws whitespace + :eol end-of-line + :eos end-of-stream + :cte comment-to-end character" + [s] + (let [c (.read s)] + (cond-let [type] + (+special-character+ c) type + (Character/isWhitespace c) :ws + :else c))) + +(defn- skip-to-end + "Skips characters on stream s until an end of stream or end of line" + [s] + (loop [c (next-char s)] + (if (#{:eol :eos} c) + c + (recur (next-char s))))) + +(defn- find-readable-this-line + "Skips characters on stream s until end of stream, end of line, or a + character of interest to the Reader. Returns :eos on end of stream, :eol + on end of line, :eol or :eos after skipping to end of line or end of + stream on semicolon, or :readable otherwise. Before returning :readable, + the readable character is pushed back onto the stream." + [s] + (loop [c (next-char s)] + (case c + :eol c + :eos c + :cte (skip-to-end s) + :ws (recur (next-char s)) + (do + (.unread s c) + :readable)))) + +(defn- read-hook + "Read hook for clojure.main/repl that keeps the compiler's line number in + sync with that of our input stream, prompts only when there is nothing + interesting remaining to read on the previous input line, and calls the + Reader only when there's something interesting to read on the current + line." + [eof] + (let [{:keys [prompt flush read]} *private*] + (loop [c (find-readable-this-line *in*)] + (case c + :eos eof + :eol + (do + (prompt) + (flush) + (recur (find-readable-this-line *in*))) + :readable + (do + (var-set Compiler/LINE (.getLineNumber *in*)) + (read eof)))))) (defn- process-inits "Processes initial pairs of args of the form: @@ -206,20 +268,19 @@ - :prompt-fmt, Prompt format string default: the prompt-fmt of the parent repl, or \"%S:%L %N=> \"" [& options] - (let [{:keys [init need-prompt prompt flush read eval print caught in out err + (let [{:keys [init prompt flush read eval print caught in out err encoding name-fmt prompt-fmt] - :or {init #() - prompt #(clojure.core/print (repl-prompt)) - need-prompt #(.atLineStart *in*) - flush flush - read read - eval eval - print prn - caught #(.println *err* (clojure.main/repl-exception %)) - in System/in - out System/out - err System/err - encoding RT/UTF8}} + :or {init #() + prompt #(clojure.core/print (repl-prompt)) + flush flush + read #(read *in* false %) + eval eval + print prn + caught #(.println *err* (clojure.main/repl-exception %)) + in System/in + out System/out + err System/err + encoding RT/UTF8}} (apply hash-map options)] (try (Var/pushThreadBindings @@ -237,14 +298,18 @@ :thread (.getId (Thread/currentThread)) :depth (inc (:depth *info*))) (assoc! *private* - :prompt prompt) + :prompt prompt + :flush flush + :read read) (set-repl-name (or name-fmt (:name-fmt *info*))) (set-repl-prompt (or prompt-fmt (:prompt-fmt *info*))) + ;; unread newline to enable first prompt + (.unread *in* (int \newline)) (clojure.main/repl :init init - :prompt prompt-hook - :flush flush - :read read + :prompt #() + :flush #() + :read read-hook :eval eval :print print :caught caught) |