Sorry for the long delay in replying. I can confirm that the console Input with Timeout works – excellent! I now understand that the O/S buffers the keypresses, and only presents them to the console input stream when the ‘Enter’ key is pressed – and thus no feedback is provided when using this code until the enter key is pressed.
For the sort of requirements that I have (simple y/n answers – with a default option), this may not be an issue. But to take this to the next level, to be able to capture keypresses as they occur would be even better. I think this requires an understanding of CURSES – for which the ‘charva’ and similar efforts are available. Just need to figure how they could be sensibly used with groovy scripts. Merlin Beedell From: Paco Zarate [mailto:conta...@nazcasistemas.com] Sent: 28 May 2015 05:54 To: users <users@groovy.incubator.apache.org> Subject: Re: Getting console input with a timeout Hello Merlin! You should be able to compile the java classes that are shown in the example (http://www.javaspecialists.eu/archive/Issue153.html f) and then use the generated jars in the groovy scripts (including the jars in the classpath). Also you can use this code directly in groovy, i tried it with groovy 2.3.9 JVM 1.8.40. This app is waits for the user to provide an input (characters + enter) for 10 seconds, it the timeout is reached, it cancels the input: File: readingConsoleWithTimeout.groovy //-- Code starts here --// import java.io.*; import java.util.concurrent.*; public class ConsoleInputReadTask implements Callable<String> { public String call() throws IOException { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); System.out.println("ConsoleInputReadTask run() called."); String input; // replacing do .. while while (true) { System.out.println("Please type something: "); try { // wait until we have data to complete a readLine() while (!br.ready()) { Thread.sleep(200); } input = br.readLine(); } catch (InterruptedException e) { System.out.println("ConsoleInputReadTask() cancelled"); return null; } if (!("".equals(input))) break; } System.out.println("Thank You for providing input!"); return input; } } public class ConsoleInput { private final int tries; private final int timeout; private final TimeUnit unit; public ConsoleInput(int tries, int timeout, TimeUnit unit) { this.tries = tries; this.timeout = timeout; this.unit = unit; } public String readLine() throws InterruptedException { ExecutorService ex = Executors.newSingleThreadExecutor(); String input = null; try { // start working for (int i = 0; i < tries; i++) { System.out.println(String.valueOf(i + 1) + ". loop"); Future<String> result = ex.submit( new ConsoleInputReadTask()); try { input = result.get(timeout, unit); break; } catch (ExecutionException e) { e.getCause().printStackTrace(); } catch (TimeoutException e) { System.out.println("Cancelling reading task"); result.cancel(true); System.out.println("\nThread cancelled. input is null"); } } } finally { ex.shutdownNow(); } return input; } } ConsoleInput con = new ConsoleInput( 1, 10, TimeUnit.SECONDS ); String input = con.readLine(); System.out.println("Done. Your input was: " + input); //-- Code ends here --// On Mon, Apr 27, 2015 at 3:57 AM, Merlin Beedell <mbeed...@cryoserver.com<mailto:mbeed...@cryoserver.com>> wrote: I am trying to get Console Input when running simple scripts that stop with questions for user input – but that a default response would be used after a short timeout. Thus a script could be run manually or run automatically. I found a handy example here http://www.javaspecialists.eu/archive/Issue153.html from Dr. Heinz M. Kabutz. However, I find that the keypresses are not echoed back to the user until the Enter key is pressed. This is a bit of a problem. It does this for both System.Console or System.in. I thought that adding thread “yield” calls might help, but they do not. I don’t know if this is a problem only when run under Groovy. Anyway, I have tried to groovy-ize the Java version below. But I wonder if the System.in MetaClass could be extended to provide the timeout functionality, rather than wrapping things on top – and would that help? Or perhaps to find a way to inject keypresses into the System.in from a separate thread, to pop the Enter keypress after the timeout? import java.util.concurrent.*; ConsoleInput con = new ConsoleInput(); String input = con.readLine("What is your name? ", "Fred", 15); //def input = con.br.readLine() //this does echo keystrokes println("Done. Your input was: " + input); input = con.readLine("What is your age? ", "50", 5); println("Done. Your input was: " + input); public class ConsoleInput { private final TimeUnit unit = TimeUnit.SECONDS; //Console cons = System.console() BufferedReader br = new BufferedReader(System.console().reader()); //This is groovies weird syntax for implementing an interface. Each map entry is a closure implementing a method of that name. // it supports the usual class implementation syntax as well, of course. def myReader = [ call: { String input; try { // wait until we have data to complete a readLine() while (!br.ready()) { Thread.yield(); Thread.sleep(200); Thread.yield(); } input = br.readLine(); } catch (InterruptedException e) { return null; } return input; } ] as Callable public String readLine(String sPrompt, String sDefault, int timeout) throws InterruptedException { print "$sPrompt [$sDefault]: " ExecutorService ex = Executors.newSingleThreadExecutor(); String input = null; //note: groovy does not support the do/while loop syntax. Strange! try { Future<String> result = ex.submit( myReader); try { input = result.get(timeout, unit); } catch (ExecutionException e) { e.getCause().printStackTrace(); } catch (TimeoutException e) { result.cancel(true); println "" //user input always has a newline - so we must add one after timeout case } } finally { ex.shutdownNow(); } return input?:sDefault; } } Merlin Beedell