Search code examples
rubycursesarrow-keys

How can I get Ruby curses to respond properly to arrow keys?


TL;DR

How can I get Ruby curses to respond properly to arrow keys? The KEY_UP constant doesn't seem to match my input.

Environment and Problem Descriptions

I am running Ruby 2.1.2 with the curses 1.0.1 gem. I'm trying to enable arrow-key navigation with curses. I've enabled Curses#getch to fetch a single key without waiting for the carriage return by calling Curses#cbreak, and this is working fine for the k character. However, I really want to enable arrow key navigation, and not just HJKL for movement.

Currently, the up-arrow prints 27 within my program, which seems like the correct ordinal value my keyboard gives for the up-arow key:

"^[[A".ord
#=> 27

and which should be matched by the Curses KEY_UP constant. It isn't, and so falls through to the else statement to display the ordinal value. The up-arrow key also leaves [A as two separate characters at the command prompt when the ruby program exits, which might indicate that Curses#getch isn't capturing the key press properly.

My Ruby Code

require 'curses'
include  Curses

begin
  init_screen
  cbreak
  noecho
  keypad = true

  addstr 'Check for up arrow or letter k.'
  refresh
  ch = getch
  addch ?\n

  case ch
  when KEY_UP
    addstr "up arrow \n"
  when ?k
    addstr "up char \n"
  else
    addstr "%s\n" % ch
  end

  refresh
  sleep 1
ensure
  close_screen
end

Solution

  • In the line to enable the keypad, you're actually creating a local variable called 'keypad' because that method is on the class Curses::Window. Since you're not making your own windows (apart from with init_screen), you can just refer to the standard one using the stdscr method. If I change line 8 to:

    stdscr.keypad = true
    

    then you sample code works for me.