4

I am working on a console application written in Java. What I have to do is handle user keyboard input. When a long process in launched with our program in a terminal, the user must have the possibility to press 'q' at anytime to stop the process (which is running on a separate thread).

I've tried several things :

  • Running in another different thread something that read user input and throws an InterruptedException to the process' thread
  • Using JLine and its ConsoleReader
  • Using JLine and add a TriggeredAction linked to a keyboard key

But each time, I face the same problem : the user has to press ENTER key, and I don't want that.

Thanks for help if you have any ideas, or the actual solution of my problem.

PS : Please, if you think this is impossible, don't answer. I know it's possible.

Olivier CLERO
  • 177
  • 15

2 Answers2

1

Perhaps you could use one of these libraries,

http://sourceforge.net/projects/jxgrabkey/ for linux

https://code.google.com/p/jintellitype/ for windows

Less related with your question, but I think can help you,

http://sourceforge.net/projects/javacurses/

The problem, with all of this, is that you will lost the platform independence.

  • Isn't JLine already capable of that, and platform independent ? – Olivier CLERO Jun 13 '13 at 15:23
  • 1
    With JLine, you can use, in the ConsoleReader the method void addTriggeredAction(char c, ActionListener listener). From addTriggeredAction JavaDoc: _Adding a triggered Action allows to give another course of action if a character passed the preprocessing. Say you want to close the application if the user enter q. addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick._ –  Jun 13 '13 at 15:35
  • http://jline.sourceforge.net/: JLine is not 100% pure Java. On Windows, it relies on a .dll file to initialize the terminal to be able to accept unbuffered input. However, no installation is necessary for this: when initialized, JLine will dynamically extract the DLL to a temporary directory and load it. For more details, see the documentation for the jline.WindowsTerminal class. On UNIX systems (including Macintosh OS X), JLine will execute the stty command to initialize the terminal to allow unbuffered input. For more details, see the documentation for the jline.UnixTerminal class. –  Jun 13 '13 at 15:44
  • I tried to add a `TriggeredAction` as I said in my question, but it does not work. Have you tried? – Olivier CLERO Jun 13 '13 at 15:53
  • 1
    Yes, I have tried. It is working fine for me. I'm using version 1.0 of JLine. I'm using the next code `getConsoleReader().addTriggeredAction('q', new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println(">>> EXECUTED"); System.exit(0); } });` –  Jun 13 '13 at 16:03
1

To avoid having the user press enter and to be able to directly respond to a keypress, we can make use of jline3 in the following way, wherein we first change the terminal into rawmode to directly respond to keys, and then wait for the next entered character.

var terminal = TerminalBuilder.terminal()
terminal.enterRawMode()
var reader = terminal.reader()

var c = reader.read()
<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline</artifactId>
    <version>3.12.3</version>
</dependency>
drcicero
  • 151
  • 2
  • 6