إدخال وحدة تحكم ذات حرف واحد في Java/clojure
-
13-09-2020 - |
سؤال
كيف يمكنني قراءة حرف/مفتاح واحد من وحدة التحكم دون الحاجة إلى الضغط على Enter؟هناك الإدخال القديم في قاعدة بيانات Sun's bug مدعيا أنه لا يمكن القيام بذلك في جافا نقية.لقد وجدت هذه الأساليب
- JNI
- جي لاين [http://jline.sourceforge.net/]
- لعنات جافا [http://sourceforge.net/projects/javacurses/]
أتوقع إضافة واحدة magic-readkey.jar
إلى مسار الفصل الخاص بي، ولكتابة بضعة أسطر من التعليمات البرمجية، مثل (def just-hit (com.acme.MagicConsole/read-char))
.
المحلول
إليك تطبيق "صدى فوري" يستخدم JLine والذي سيتم طباعته int
يتوافق مع ضغطات المفاتيح المسجلة، ويتم تنظيمه على شكل ملف لينينجن مشروع:
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)))))
يتم توفير الوظيفة المعنية بواسطة jline.Terminal
فئة توفر طريقة ثابتة getTerminal
إرجاع مثيل لفئة فرعية خاصة بالنظام الأساسي والتي يمكن استخدامها للتفاعل مع الجهاز.انظر جافادوك لمزيد من التفاصيل.
دعونا نرى ماذا asdf
يشبه...
$ java -jar con-1.0.0-SNAPSHOT-standalone.jar
97
115
100
102
(نسخة لا يزال يقتل التطبيق بالطبع.)
نصائح أخرى
لأي شخص قد يقرأ هذا في عام 2015 وما بعده، لاحظ أن الإصدارات الأحدث من JLine لم تعد تمتلك الطريقة Terminal/getTerminal
.أنا متأكد من أن هناك طريقة أخرى (وربما أفضل) للقيام بذلك الآن باستخدام JLine2، ولكن يمكنك دائمًا استخدامها jline "0.9.94"
وستظل الإجابة المقبولة صالحة، على الأقل حتى Clojure 1.6 (من الجدير بالذكر أنك لم تعد بحاجة إلى طلب clojure.contrib
).
كبديل، أود أن أوصي بالممتاز clojure-فانوس, ، وهو عبارة عن غلاف Clojure حول Java الفانوس مكتبة.كما ترون في المستندات, ، هناك get-key
و get-key-blocking
وظائف للقراءة في أحرف واحدة من الإدخال.
إذا كنت تريد استخدام jline2 فهناك ConsoleReader
الطبقة المتاحة والتي تفعل إلى حد كبير نفس الشيء الذي أوضحه Michał Marczyk أعلاه:
(ns con.core
(:import jline.console.ConsoleReader)
(:gen-class))
(defn -main [& args]
(while true (->> (ConsoleReader.) (.readCharacter) (println))))