groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paco Zarate <conta...@nazcasistemas.com>
Subject Re: Getting console input with a timeout
Date Thu, 28 May 2015 04:54:04 GMT
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 <MBeedell@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
>
>
>

Mime
View raw message