PlacateTheCattin
PlacateTheCattin

Reputation: 1486

How to capture some special key presses for Ruby input prompt in Terminal (and let others through normally)

I am in a Ruby script something like:

something = gets      # or STDIN.gets
puts something

def arrow_pressed
    puts "arrow totally pressed"
end

Once the user prompt exists I want all keyboard input to happen normally except for the arrow keys. If those are pressed I don't want anything to appear in the terminal (e.g. ^[[A). I just want to execute my arrow_pressed method. And I want to execute it without the user needing to hit Return

I already tried this gist - which works well except that even after changing it to let through most keystrokes normally, I still can't get Backspace (or other specials) to work.

I'm happy to use something other than gets (a library or whatever). Any help would be appreciated!

Upvotes: 4

Views: 2175

Answers (2)

Piotr Murach
Piotr Murach

Reputation: 547

I'm the author of tty-reader that provides a higher-level API for handling keyboard input. Using it you can read a single keypress, entire line or multiline content. It also allows you to listen for different key events like key up or backspace.

For example, to prompt the user for input and perform actions when arrows or backspace are pressed:

require "tty-reader"

reader = TTY::Reader.new

reader.on(:keydown) { puts "down we go" }
      .on(:keyup) { puts "up we go" }
      .on(:keybackspace) { puts "backspace pressed" }

answer = reader.read_line

The gem has been tested to work on all major platforms including Windows.

Upvotes: 5

Stefan
Stefan

Reputation: 114178

You could use getch but since arrow keys are given as ANSI escape sequences, some parsing is required:

require 'io/console'

loop do
  case $stdin.getch
  when 'q'    then exit
  when "\c?"  then puts 'backspace'
  when "\e"   # ANSI escape sequence
    case $stdin.getch
    when '['  # CSI
      case $stdin.getch
      when 'A' then puts 'up'
      when 'B' then puts 'down'
      when 'C' then puts 'right'
      when 'D' then puts 'left'
      end
    end
  end
end

This is just an example. There are many other escape sequences you'll have to consider.

Upvotes: 3

Related Questions