Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect key presses on console?

I'm writing a roguelike in Scala. I need to be able to see when the user presses an arrow key for example. All of the solutions I have found require the player to press enter.

Is there any way to detect keypresses in a console app in a similar manner to getch() in C?

like image 576
Serentty Avatar asked Dec 20 '11 21:12

Serentty


2 Answers

The problem with Enter is that terminal buffers input, so you need to turn it to raw mode. Note that it is a platform-specific issue, so it is not very portable.

Look at answers to this question: How to read a single char from the console in Java (as the user types it)?

Short answer for UNIX systems:

import sys.process._
(Seq("sh", "-c", "stty -icanon min 1 < /dev/tty") !)
(Seq("sh", "-c", "stty -echo < /dev/tty") !)

(1 to 20).foreach { _ =>
  val c = Console.in.read
  println("Got " + c)
}
like image 183
Rogach Avatar answered Oct 17 '22 22:10

Rogach


Scala includes jline in its distribution (with slightly modified packaging), since it uses it in the REPL. It's not normally loaded, but if you know where your Scala lib directory is, you can add it to the classpath. If you add it to the classpath, then this will work:

object Key extends App {
  val con = new tools.jline.console.ConsoleReader()
  println( con.readVirtualKey() )
}

(note that this method will give ^P ^N ^B ^F for up, down, left, and right, respectively, matching the standard control keys). But this will also override the standard behavior of System.in.read(), so you can pass it arrays of length 1 to get the next waiting byte (and test for waiting bytes with System.in.available, which should be more than 1 for arrow keys).

like image 27
Rex Kerr Avatar answered Oct 17 '22 23:10

Rex Kerr