Domanda

Come posso ottenere un singolo carattere della tastiera dal terminale con Ruby senza premere Invio? Ho provato Curses :: getch , ma non ha funzionato davvero per me.

È stato utile?

Soluzione

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

(Testato sul mio sistema OS X, potrebbe non essere portatile su tutte le piattaforme Ruby). Vedi http://www.rubyquiz.com/quiz5.html per alcuni suggerimenti aggiuntivi, tra cui per di Windows.

Altri suggerimenti

Da ruby ??2.0.0, c'è uno 'io / console' nello stdlib con questa funzione

require 'io/console'
STDIN.getch

@Jay ha dato un'ottima risposta, ma ci sono due problemi:

  1. È possibile incasinare lo stato tty predefinito;
  2. Si ignorano i caratteri di controllo (^ C per SIGINT, ecc.).

Una soluzione semplice è quella di salvare il precedente stato tty e utilizzare i seguenti parametri:

  • -icanon - disabilita l'input canonico (elaborazione ERASE e KILL);
  • isig - abilita il controllo dei caratteri rispetto agli speciali caratteri di controllo INTR, QUIT e SUSP.

Alla fine avresti una funzione come questa:

def get_char
  state = `stty -g`
  `stty raw -echo -icanon isig`

  STDIN.getc.chr
ensure
  `stty #{state}`
end

La modalità Raw ( stty raw -echo ) sfortunatamente fa sì che control-C venga inviato come personaggio, non come SIGINT. Quindi, se vuoi bloccare l'input come sopra, ma consenti all'utente di premere control-C per arrestare il programma mentre è in attesa, assicurati di farlo:

Signal.trap("INT") do # SIGINT = control-C
  exit
end

E se vuoi un input non bloccante, cioè controlla periodicamente se l'utente ha premuto un tasto, ma nel frattempo vai a fare altre cose, allora puoi farlo:

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

Si noti che non è necessario un gestore SIGINT speciale per la versione non bloccante poiché tty è in modalità raw solo per un breve momento.

Nota: questa è una vecchia risposta e la soluzione non funziona più sulla maggior parte dei sistemi.

Ma la risposta potrebbe ancora essere utile per alcuni ambienti, dove gli altri metodi non funzionano. Si prega di leggere i commenti qui sotto.


Per prima cosa devi installare highline:

gem install highline

Quindi prova se il metodo highline funziona per te:

require "highline/system_extensions"
include HighLine::SystemExtensions

print "Press any key:"
k = get_character
puts k.chr

E se stai creando un'applicazione maledizioni , devi chiamare

nocbreak

http: //www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top