clojure

2025-08-09T13:22:34.683779Z

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

emccue 2025-08-10T14:29:30.852489Z

https://github.com/pot/boba

๐Ÿ˜ 1
2025-08-11T11:58:40.234089Z

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.

borkdude 2025-08-11T12:00:13.758039Z

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))

p-himik 2025-08-09T13:25:59.145739Z

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.

igrishaev 2025-08-09T13:32:24.239449Z

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

2025-08-09T13:34:20.517129Z

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

borkdude 2025-08-09T13:38:12.066109Z

Here's one workaround https://clojurians.slack.com/archives/CLX41ASCS/p1677150483083619

๐Ÿ†’ 1
Joe Lane 2025-08-09T15:15:54.472099Z

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

emccue 2025-08-09T20:00:18.498919Z

I have been actively working on this

emccue 2025-08-09T20:00:33.683389Z

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

gaverhae 2025-08-09T22:39:58.832859Z

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.

emccue 2025-08-10T00:44:59.166469Z

(got distracted, forgot to link)

emccue 2025-08-10T00:45:01.545639Z

(1 sec)