3

I'm writing a small script in Ruby that reads input from the command line.

I would like to catch the up , down , left, right arrow signal. I want to do something like in the Terminal. (when you hit up-arrow you have the previous command ...) How can I do that?

3

2 Answers 2

2

To do completely unbuffered input you can use something like termios. However you will have to interpret arrow key sequences manually.

If you can live with a middle layer for history completion I suggest using GNU readline, like mentioned previously, or the RawLine library by H3RALD:

http://www.h3rald.com/rawline/
http://www.h3rald.com/articles/real-world-rawline-usage/

Example of unbuffered input with termios:

require 'rubygems'
require 'termios'

def with_unbuffered_input
  old_attrs = Termios.tcgetattr(STDOUT)

  new_attrs = old_attrs.dup

  new_attrs.lflag &= ~Termios::ECHO
  new_attrs.lflag &= ~Termios::ICANON

  Termios::tcsetattr(STDOUT, Termios::TCSANOW, new_attrs)

  yield
ensure
  Termios::tcsetattr(STDOUT, Termios::TCSANOW, old_attrs)
end

with_unbuffered_input do
  10.times {
    c = STDIN.getc
    puts "Got #{c}"
  }
end
Sign up to request clarification or add additional context in comments.

Comments

0

Starting with ruby 1.9.3, io/console is shipped with ruby. One can use its #raw to achieve unbuffered input:

http://ruby-doc.org/stdlib-2.2.2/libdoc/io/console/rdoc/IO.html#method-i-raw

However, arrow keys are represented by a sequence of characters, not a single character. This sequence always starts with "\e" but unfortunately there isn't any end-of-sequence marker.

Something like this could be used to read arrow keys:

require 'io/console'
require 'timeout'

def readkey
  c = ''
  result = ''
  $stdin.raw do |stdin|
    c = stdin.getc
    result << c
    if c == "\e"
      begin
        while (c = Timeout::timeout(0.0001) { stdin.getc })
          result << c
        end
      rescue Timeout::Error
        # no action required
      end
    end
  end
  result
end

puts readkey.inspect #=> outputs "\e[D" if left arrow is pressed

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.