كيفية الحصول على حرف واحد دون الضغط على زر الإدخال؟
سؤال
كيف يمكنني الحصول على حرف لوحة مفاتيح واحد من الجهاز باستخدام Ruby دون الضغط على زر الإدخال؟حاولت Curses::getch
, ، لكن هذا لم ينجح حقًا بالنسبة لي.
المحلول
HTTP: //blade.nagaokaut. ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/2999
#!/usr/bin/ruby
begin
system("stty raw -echo")
str = STDIN.getc
ensure
system("stty -raw echo")
end
p str.chr
و(اختبار على نظام بلدي X OS، قد لا تكون محمولة على جميع المنابر روبي). انظر http://www.rubyquiz.com/quiz5.html للحصول على بعض الاقتراحات الإضافية، بما في ذلك النوافذ.
نصائح أخرى
ومنذ روبي 2.0.0، هناك "الإعلام والتوعية / وحدة التحكم" في stdlib مع هذه الميزة
require 'io/console'
STDIN.getch
أعطى @Jay إجابة رائعة، ولكن هناك مشكلتان:
- يمكنك إفساد حالة tty الافتراضية؛
- أنت تتجاهل أحرف التحكم (^C لـ SIGINT، وما إلى ذلك).
الحل البسيط لذلك هو حفظ حالة tty السابقة واستخدام المعلمات التالية:
-icanon
- تعطيل الإدخال المتعارف عليه (معالجة المسح والقتل)؛isig
- تمكين التحقق من الأحرف مقابل أحرف التحكم الخاصة INTR وQUIT وSUSP.
في النهاية سيكون لديك وظيفة مثل هذا:
def get_char
state = `stty -g`
`stty raw -echo -icanon isig`
STDIN.getc.chr
ensure
`stty #{state}`
end
ووضع الأولية (stty raw -echo
) يسبب سوء الحظ السيطرة-C للحصول أرسلت في كحرف، وليس بوصفه SIGINT. حتى إذا كنت تريد منع إدخال مثل أعلاه، ولكن تسمح للمستخدم لضرب تحكم-C لوقف البرنامج في حين انها تنتظر، تأكد للقيام بذلك:
Signal.trap("INT") do # SIGINT = control-C
exit
end
وإذا كنت تريد غير مؤمن الإدخال - وهذا هو، تحقق بشكل دوري إذا قام المستخدم الضغط على مفتاح، ولكن في هذه الأثناء، تذهب تفعل أشياء أخرى - ثم يمكنك القيام بذلك:
require 'io/wait'
def char_if_pressed
begin
system("stty raw -echo") # turn raw input on
c = nil
if $stdin.ready?
c = $stdin.getc
end
c.chr if c
ensure
system "stty -raw echo" # turn raw input off
end
end
while true
c = char_if_pressed
puts "[#{c}]" if c
sleep 1
puts "tick"
end
ملحوظة أنك لا تحتاج إلى معالج SIGINT خاص لغير مؤمن نسخة منذ TTY هو فقط في وضع الخام للحظة وجيزة.
ملاحظة: هذا هو الجواب والقديمة والحل لم يعد يعمل على معظم أنظمة
.ولكن الجواب يمكن أن يكون مفيدا لبعض البيئات، حيث لا تعمل الطرق الأخرى. يرجى قراءة التعليقات أدناه.
وأول لديك لتثبيت HIGHLINE:
gem install highline
وإذا ثم حاول يعمل الأسلوب HIGHLINE لك:
require "highline/system_extensions"
include HighLine::SystemExtensions
print "Press any key:"
k = get_character
puts k.chr
وإذا كنت بناء اللعنات التطبيق، تحتاج إلى الاتصال
nocbreak
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak