I am new to Clojure, I wish to create a command line in clojure.
I am using lein, The app is simply waiting for user to type something and when press enter, it will print the line.
I cannot seems to make Clojure wait forever with lein run
Is there any other way?
Here is my code.
(defn -main [& args]
(read-line)
)
so when I type something and press enter, the whole code stops,
I want to take the input of user typing and process it continuously.
I mean each time user press enter, he/she should be able to continue to next line and program will run forever.
You need to loop for the user inputs then and provide some means to break the loop (yet, ctrl-c also works). E.g.
(loop []
(let [input (read-line)]
(if (= input "quit")
(println "bye")
(do
(println "You said: " input)
(recur)))))
Related
How can I get readline-like (or rlwrap-like) functionality from my REPL when I use the repl function from clojure.main?
The background to this is that I'm utilizing and customizing the break function from The Joy of Clojure, First Edition. I'm using it from inside the lein repl REPL. When my "breakpoint" kicks in, the readline-like functionality of Leiningen's REPL is gone, which is kind of inconvenient. My muscle memory makes me hit ↑ followed quickly by Enter. Before I can stop myself, I've got this in my terminal:
debug=> ^[[A
CompilerException java.lang.RuntimeException: Unable to resolve symbol: in this context, compiling:(/tmp/form-init13211381000659590518.clj:1:1)
And now my REPL is stuck and I have to kill the terminal or the process to get out. I'd like very much if I could either get readline working in this second-level REPL or at least prevent this common issue from derailing my debug sessions.
You should use rebel readline, a new repl for clojure developed by bhauman the same guy who brought is figwheel.
https://github.com/bhauman/rebel-readline
It has rlwrap features, syntax highlighting and multi line code editing all in the terminal.
I'm not sure the rlwrap utility would help there, because the inner REPL is held by the outer one. So the input is being controlled by Java code, not the rlwrap tool.
You are causing an exception since you input a wrong value. I remember, the clojure.main/repl function might take an additional argument to handle exceptions. Probably, you could handle it somehow and just print a string "wrong input value" instead. Take a look at the documentation for REPL.
Also, you may implement your own REPL for debugging. Long ago, I used to write some kind of it, here what I've got:
(defn repl []
(let [input (read)]
(if (= input 'q)
nil
(do
(try
(let [result (eval input)]
(println result))
(catch Exception e
(println e)))
(recur)))))
That function just prompts for a proper Clojure expression in an endless loop, evaluates it and prints the result. In case of a wrong input, it prints the error and carries on. To leave the REPL, input q.
Example:
(repl)
(+ 1 2) ;; 2
fsdf8 9_fsd ;; prints a stack trace
q ;; returns nil and exit
Try Emacs with Cider as your repl. When you (break) you'll be bumped out of the Cider repl and into the Emacs Minibuffer, where your standard emacs editing shortcuts (upon which readline is modeled) continue to apply.
I'm writing a generic function that asks for input from the user, validates it via a passed function, and displays a message if the input is bad.
The problem I'm facing is the message asking for input doesn't actually print until after the user has already given the input.
Since I'm using print instead of println, stream buffering is the obvious culprit, but even after flushing after printing, it still doesn't print at the right time. Here's the simplest example of the problem:
(defn- fprint [message]
(print message)
(flush))
(defn simple-interact []
(fprint "123")
(fprint (read-line))
(fprint "456"))
Using IntelliJ IDEA's REPL, running this causes a popup input prompt. If I enter abc into the prompt, it prints 123abc456 at once instead of in parts; 123 isn't printed until after I've already given the input.
I'm using print instead of println because the real function I'm writing displays a given message, and I don't want to force it to print a newline if the intial message is intended to be a prompt. For reference, here's the full function and helpers:
(defn- print-mesage? [message]
(and message (not= message "")))
(defn- fprint [message]
(print message)
(flush))
(defn- fprint? [message]
(if (print-mesage? message)
(fprint message)))
(defn restricted-ask-for-input
"Asks a user for input. Will repeatedly ask until their input is verified via validate-f.
The ask message is displayed once before input is first asked for.
The error message is displayed every time validation fails.
If either of the messages is empty, or falsey, they won't be printed.
The messages dont' have a newline added after them."
[ask-message error-message validate-f]
(fprint? ask-message)
(loop []
(let [in (read-line)]
(if (validate-f in)
in
(do
(fprint? error-message)
(recur))))))
I really need to be able to print prior to asking for input so the user knows what's being asked.
Any help here would be appreciated.
Just as a test after posting this I tried changing fprint to use println instead, and the behavior is the same.
I'm trying to translate a small console program I wrote in Java into Clojure, but I'm having a little trouble figuring out the difference between Clojure's standard *out* var and the object at System/out. I was under the impression that they were the same thing, but when during my testing they seem to be different.
In my program I prompt the user to enter a number, and I want the prompt and input text to be on the same line. In Java, I printed the prompt with System.out.print() and then a Scanner read the input.
The following was my first attempt at something similar in Clojure. Though the print function seems like it should fire before the read-line, it immediately blocks on input and prints everything after in a jumbled mess:
(defn inp1 []
(print "Enter your input: ")
(let [in (read-line)]
(println "Your input is: " in)))
The following was my next attempt, using *out*. It suffers from the same problem as the function above:
(defn inp2 []
(.print *out* "Enter input: ")
(let [i (read-line)]
(println "You entered: " i)))
On my third try, I finally got it to work by using System/out directly:
(defn inp3 []
(let [o System/out]
(.print o "Enter input: ")
(let [i (read-line)]
(println "You entered: " i))))
I'm glad I finally got it to work, but I'm deeply confused as to why the third one works the way I want when the first two don't. Why do the first two block immediately? Can anyone shed some light on this?
Per the docs:
*out* - A java.io.Writer object representing standard output for print operations.
Defaults to System/out, wrapped in an OutputStreamWriter
...so, you have a layer of wrapping. Looking at the docs for that layer (emphasis added):
Each invocation of a write() method causes the encoding converter to be invoked on the given character(s). The resulting bytes are accumulated in a buffer before being written to the underlying output stream. The size of this buffer may be specified, but by default it is large enough for most purposes. Note that the characters passed to the write() methods are not buffered.
...emphasis added. Since OutputStreamWriter buffers, you need to call .flush to force content to be written.
I'm writing a Brainf*** interpreter in Clojure. I want to pass a program in using stdin. However, I still need to read from stdin later for user input.
Currently, I'm doing this:
$ cat sample_programs/hello_world.bf | lein trampoline run
My Clojure code is only reading the first line though, using read-line:
(defn -main
"Read a BF program from stdin and evaluate it."
[]
;; FIXME: only reads the first line from stdin
(eval-program (read-line)))
How can I read all the lines in the file I've piped in? *in* seems to be an instance of java.io.Reader, but that only provides .read (one char), .readLine (one line) and read(char[] cbuf, int off, int len) (seems very low level).
It's simple enough to read all input data as a single string:
(defn -main []
(let [in (slurp *in*)]
(println in)))
This works fine if your file can fit in available memory; for reading large files lazily, see this answer.
you could get a lazy seq of lines from *in* like this:
(take-while identity (repeatedly #(.readLine *in*)))
or this:
(line-seq (java.io.BufferedReader. *in*))
which are functionally identical.
I am writing a text game in Clojure. I want the player to type lines at the console, and the game to respond on a line-by-line basis.
Research showed me that (read-line) is the way one is meant to get text lines from standard input in Clojure, but it is not working for me.
I am in a fresh Leiningen project, and I have added a :main clause to the project.clj pointing to the only source file:
(ns textgame.core)
(defn -main [& args]
(println "Entering -main")
; (flush) ;makes no difference if flush are commented out
(let [input (read-line)]
(println "ECHO:" input))
; (flush)
(println "Exiting -main"))
using lein run yields:
Entering -main
ECHO: nil
Exiting -main
In other words, there is no opportunity to enter text at the console for (read-line) to read.
How should I get Clojure to wait for characters and newline to be entered and return the corresponding string?
(I am using GNOME Terminal 2.32.1 on Linux Mint 11, Leiningen 1.6.1.1 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM, Clojure version 1.2.1.)
Update: If I run lein repl, I can (println (read-line)), but not when I have a -main function and run using lein run.
Try "lein trampoline run". See http://groups.google.com/group/leiningen/browse_thread/thread/a07a7f10edb77c9b for more details also from https://github.com/technomancy/leiningen:
Q: I don't have access to stdin inside my project.
A: There's a problem in the library that Leiningen uses to spawn new processes that blocks access to console input. This means that functions like read-line will not work as expected in most contexts, though the repl task necessarily includes a workaround. You can also use the trampoline task to launch your project's JVM after Leiningen's has exited rather than launching it as a subprocess.
I have had similar problems and resorted to building a jar file and then running that.
lein uberjar
java -jar project-standalone.jar
It's a bit slower, though it got me unstuck. An answer that works from the repl would
be better
Wrap your read-line calls with the macro with-read-line-support which is now in ns swank.core [since swank-clojure 1.4+ I believe]:
(use 'swank.core)
(with-read-line-support
(println "a line from Emacs:" (read-line)))
Thanks to Tavis Judd for the fix.
You can use read and use a string as input.
Not sure about the lein aspects of the problem, but definitely in emacs it is impossible to make stdin work. However, if you want to get text from the user, you can easily do it using a JOptionPane like this code from my little tic-tac-toe program:
(defn get-input []
(let [input (JOptionPane/showInputDialog "Enter your next move (row/column)")]
(map #(Integer/valueOf %) (.split input "/"))))