Consider I have a Java (or Kotlin, doesn't really matter) application which uses java.io.Console
API, or any other API which manipulates the terminal state (e.g.: net.rubygrapefruit:native-platform
):
System.out.println(format("Console is %s.", System.console()));
final Terminals terminals = Native.get(Terminals.class);
final Output out = Stdout;
if (terminals.isTerminal(out)) {
final TerminalOutput stdout = terminals.getTerminal(out);
stdout.bold();
System.out.println("bold text");
stdout.foreground(Color.Magenta);
System.out.println("Magenta");
stdout.reset();
final Prompter prompter = new Prompter(terminals);
prompter.askYesNo("Prompt", true);
prompter.enterText("Text", "default text");
prompter.enterPassword("Password");
prompter.select("Select", asList("foo", "bar", "baz"), 1);
} else {
System.out.println(format("%s is not a terminal.", out));
}
The above code would run just fine when launched by Maven Exec plug-in, but with Gradle (since Gradle tries to make its own output look pretty, with all those bells, whistles and progress bars) the code just prints:
$ gradle --console=plain run
> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :run
Console is null.
Stdout is not a terminal.
BUILD SUCCESSFUL in 0s
2 actionable tasks: 1 executed, 1 up-to-date
Configuring the run
task as described here and here:
private val run: JavaExec by tasks
run.apply {
standardInput = System.`in`
standardOutput = System.out
errorOutput = System.err
}
or adding --no-daemon
to Gradle's command line args as suggested here doesn't really help (System.in
is still an instance of java.io.PipedInputStream
, while System.out
and System.err
are instances of org.gradle.internal.io.LinePerThreadBufferingOutputStream
).
Is it possible to make Gradle stop messing with the terminal and allow the application being run to access it?