clojure 2025-08-09

Hey all, any tips about how to handle with terminal inputs on Clojure? I saw some old posts recommening the https://github.com/MultiMUD/clojure-lanterna library, but it seems to not being mantained. Is there any other option? My goal is to be able to get all user key pressed on terminal

Nice, thank you all, I'll try the suggestions ๐Ÿ™ My use case is very simple, just read the keys and need to clear the terminal also. But, I want to work on Windows also.

I asked chatgpt for a portable version of the hack above and it came up with this. FWIW, I didn't test it.

(require '[clojure.string :as str])

(defn read-char-portable []
  (let [os (System/getProperty "os.name")]
    (if (.startsWith os "Windows")
      ;; PowerShell ReadKey
      (let [cmd (into-array String
                            ["powershell" "-NoProfile" "-Command"
                             "$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').Character"])
            pb  (ProcessBuilder. cmd)]
        ;; IMPORTANT: let the subprocess read from the same TTY
        (.redirectInput pb java.lang.ProcessBuilder$Redirect/INHERIT)
        (let [p (.start pb)]
          (with-open [r (.getInputStream p)]
            (str/trim (slurp r)))))

      ;; POSIX: use stty + dd, with trap to restore terminal state
      (let [bash-cmd "trap 'stty sane' EXIT; stty -echo -icanon time 0 min 1; dd bs=1 count=1 status=none 2>/dev/null"
            cmd (into-array String ["bash" "-c" bash-cmd])
            pb  (ProcessBuilder. cmd)]
        ;; IMPORTANT: let the subprocess read from the same TTY
        (.redirectInput pb java.lang.ProcessBuilder$Redirect/INHERIT)
        (let [p (.start pb)]
          (with-open [r (.getInputStream p)]
            (str/trim (slurp r)))))))

;; Example:
(println "Press a key:")
(println "You pressed:" (read-char-portable))

Without any second thoughts, I would look up how to do it in Java and would just do that. The goal is very simple, there's no need for any libraries to achieve that. Unless, of course, what Java offers is utterly incompetent somehow. Then there's no need for Clojure libraries here, some Java library probably already exists.

I believe this SO topic has some relevant code snippets: https://stackoverflow.com/questions/17538182/getting-keyboard-input tl;dr: Clojure doens't bring any tools for reading keys. You need to use http://java.io guts

thanks @p-himik @igrishaev,I'll take a look to Java ๐Ÿ˜‡

You can also use the Java โ€œforeign memory apiโ€œ to call out to any library / language that supports FFI you might find that does what you desire. https://docs.oracle.com/en/java/javase/21/core/foreign-function-and-memory-api.html

I have been actively working on this

or rather, i made some progress then someone else picked up my slack

I recently did something like that, see here: https://github.com/gaverhae/misc/pull/363/files Very similar to Borkdude's sample above, just using clojure.java.process instead. If you need something more complicated, JLine would be the first place I look.

(got distracted, forgot to link)