Entering a single character console in java / clojure

How can I read one character / key from the console without pressing Enter? There is an old entry in the Sun database stating that this cannot be done in pure java. I found these approaches

I expect to add one magic-readkey.jar to my classpath and write a few lines of code, for example (def just-hit (com.acme.MagicConsole/read-char)) .

+6
source share
3 answers

Here's an “instant echo” application using JLine that will print an int corresponding to registered keystrokes structured as a Leiningen project:

  • project.clj :

     (defproject con "1.0.0-SNAPSHOT" :description "FIXME: write" :main con.core :dependencies [[org.clojure/clojure "1.1.0"] [org.clojure/clojure-contrib "1.1.0"] [jline "0.9.94"]]) 
  • src/con/core.clj :

     (ns con.core (:import jline.Terminal) (:gen-class)) (defn -main [& args] (let [term (Terminal/getTerminal)] (while true (println (.readCharacter term System/in))))) 

This functionality is provided by the jline.Terminal class, which provides a static getTerminal method that returns an instance of a subclass for a specific platform that can be used to interact with the terminal. See Javadoc for more details.

Let's see how asdf looks ...

 $ java -jar con-1.0.0-SNAPSHOT-standalone.jar 97 115 100 102 

( Cc still kills the application, of course.)

+11
source

For those who can read this in 2015 and beyond, note that later versions of JLine no longer have the Terminal/getTerminal . I'm sure there is another (possibly better) way to do it now with JLine2, but you can always just use jline "0.9.94" and the accepted answer will still work, at least until Clojure 1.6 (please note: it takes more time clojure.contrib ).

As an alternative, I would recommend the excellent clojure-lanterna , which is a Clojure wrapper around Java Lanterna . As you can see in the docs , there are get-key and get-key-blocking functions for reading in single input characters.

+3
source

If you want to use jline2, there is a ConsoleReader class that does almost the same thing as Michael Marchik explained:

 (ns con.core (:import jline.console.ConsoleReader) (:gen-class)) (defn -main [& args] (while true (->> (ConsoleReader.) (.readCharacter) (println)))) 
+1
source

All Articles