(.module: [lux #* [control [monad (#+ do)]] [data ["e" error] ["." text]] [concurrency ["." promise] ["." task (#+ Task)]] [type [object interface]] ["." io (#+ IO Process io)] [host (#+ import:)]]) (interface: #export Console (read-char [] (Task Text)) (read-line [] (Task Text)) (write [Text] (Task Any)) (close [] (Task Any))) (for {"JVM" (as-is (import: java/io/InputStream (read [] #io #try int) (available [] #io #try int) (mark [int] #io #try void) (reset [] #io #try void)) (import: java/io/Reader) (import: java/io/PrintStream (print [String] #io #try void)) (import: java/lang/System (#static in java/io/InputStream) (#static out java/io/PrintStream)) (import: java/lang/Appendable (append [CharSequence] Appendable)) (import: java/lang/String) (import: java/lang/StringBuffer (new [String]) (toString [] String)) (class: JVM-Console Console {#input InputStream #output PrintStream} (def: read-char (|>> get@Console (get@ #input) (InputStream::read []) (:: io.Functor map (|>> .nat text.from-code)) promise.future)) (def: (read-line console) (let [input (|> console get@Console (get@ #input)) buffer (StringBuffer::new [""])] (promise.future (loop [_ []] (do io.Monad [char (<| (:: @ map (|>> .nat text.from-code)) (InputStream::read [] input))] (case char "\n" (wrap (StringBuffer::toString [] buffer)) "\r" (do @ [available (InputStream::available [] input)] (if (i/> 0 available) (do @ [_ (InputStream::mark [10] input) next (<| (:: @ map (|>> .nat text.from-code)) (InputStream::read [] input))] (case next "\n" (wrap (StringBuffer::toString [] buffer)) _ (do @ [_ (InputStream::reset [] input)] (wrap (StringBuffer::toString [] buffer))))) (wrap (StringBuffer::toString [] buffer)))) _ (exec (Appendable::append [(:coerce String char)] buffer) (recur [])))))))) (def: (write message) (|>> get@Console (get@ #output) (PrintStream::print [message]) promise.future)) (def: (close self) (task.return []))) (def: #export open (Process Console) (io (#e.Success (new@JVM-Console {#input System::in #output System::out}))))) })