Ingresso console a carattere singolo in Java/clojure
-
13-09-2020 - |
Domanda
Come posso leggere un singolo carattere/tasto dalla console senza dover premere Invio?C'è un vecchia voce nel database dei bug di Sun sostenendo che non può essere fatto in puro Java.Ho trovato questi approcci
- JNI
- JLine [http://jline.sourceforge.net/]
- Maledizioni Java [http://sourceforge.net/projects/javacurses/]
Mi aspetterei di aggiungerne uno singolo magic-readkey.jar
al mio percorso di classe e scrivere alcune righe di codice, tipo (def just-hit (com.acme.MagicConsole/read-char))
.
Soluzione
Ecco un'app "eco immediata" che utilizza JLine che verrà stampata int
s corrispondente alle pressioni dei tasti registrate, strutturato come a Leiningen progetto:
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)))))
La funzionalità in questione è fornita da jline.Terminal
class, che fornisce un metodo statico getTerminal
restituendo un'istanza di una sottoclasse specifica della piattaforma che può essere utilizzata per interagire con il terminale.Vedi il Javadoc per ulteriori dettagli.
Vediamo cosa asdf
sembra...
$ java -jar con-1.0.0-SNAPSHOT-standalone.jar
97
115
100
102
(C-c uccide comunque l'app, ovviamente.)
Altri suggerimenti
Per chiunque possa leggere questo nel 2015 e oltre, si noti che le versioni più recenti di Jline non hanno più il metodo Terminal/getTerminal
.Sono sicuro che c'è un altro modo (forse migliore) per farlo ora con Jline2, ma puoi sempre usare jline "0.9.94"
e la risposta accettata funzionerà ancora, almeno fino a Clojure 1.6 (di nota, non è più necessario richiedereclojure.contrib
).
Come alternativa, consiglierei l'eccellente clojure-lanterna , che è un involucro di clojureintorno a Java lanterna libreria.Come puoi vedere in I Documenti , ci sono get-key
e get-key-blocking
funzioni per la letturain singoli caratteri di input.
Se si desidera utilizzare Jline2 c'è una classe ConsoleReader
disponibile che fa praticamente la stessa cosa Michał Marczyk ha spiegato sopra:
(ns con.core
(:import jline.console.ConsoleReader)
(:gen-class))
(defn -main [& args]
(while true (->> (ConsoleReader.) (.readCharacter) (println))))
.