Как я могу прочитать один символ из STDIN в Clojure? - PullRequest
0 голосов
/ 26 октября 2019

Я пишу цикл, который работает только на односимвольных вводах. В зависимости от того, что пользователь нажал ( без нажатия ENTER ), я хочу отобразить, какую клавишу набрал пользователь, а затем повторить. Если пользователь нажимает «q», цикл должен завершиться.

Ограничения:

  • Меня не волнует Unicode (желательна только поддержка набора символов США ASCII).
  • Я забочусь только о системах Unixy (подходит только Linux).
  • Я использую Leiningen.

Можно ли это сделать? Некоторые поиски привели меня к jline2, в котором был класс ConsoleReader, но, похоже, он исчез в jline3.

1 Ответ

2 голосов
/ 28 октября 2019

Я видел https://gist.github.com/mikeananev/f5138eeee12144a3ca82136184e7a742 и, используя связанный дублированный ответ, придумал следующее:

; Need `(:import [org.jline.terminal TerminalBuilder Terminal])`

(defn new-terminal
  "creates new JLine3 Terminal.
  returns terminal object"
  ^Terminal [term-name]
  (let [terminal (-> (TerminalBuilder/builder)
                     (.jna true)
                     (.system true)
                     (.name term-name)
                     (.build))]
    terminal))

(defn interactive-loop []
  (let [t (new-terminal "xxx")]
    (.enterRawMode t)
    (let [reader (.reader t)]
    (loop [char-int (.read reader)]
      (case (char char-int)
        \q (do
          (println "Bye!")
          (.close reader)
          (.close t))
        (do (println (char char-int))
            (recur (.read reader))))))))

Я на NixOS и, очевидно, библиотека jline3 зависит от двоичного существа infocmpустановлен, который является частью популярного пакета ncurses. К сожалению, версия Nixpkgs, которую я использую в настоящее время, не упаковывает этот бинарный файл, поэтому я вставил PR здесь:

...