spring-projects / spring-shell

Spring based shell
http://projects.spring.io/spring-shell/
Apache License 2.0
719 stars 395 forks source link

How to pipe to standard input #1037

Open rj93 opened 4 months ago

rj93 commented 4 months ago

Hi,

I am trying to find out how to pipe to a commands standard input.

Taking the quick start example:

java -jar demo-0.0.1-SNAPSHOT.jar hello-world boot

I would like to be able to achieve:

echo "boot" | java -jar demo-0.0.1-SNAPSHOT.jar hello-world
jvalkeal commented 4 months ago

Unfortunately this is not yet supported. There's been a recent work in JLine making process input/output easier to handle so hopefully we're able to implement these features.

rj93 commented 4 months ago

Forgive my naivety, but why couldn't a simple InputStreamReader be used to read in from the pipe?

It is fairly safe to assume that when using a pipe a program would be ran in not interactive mode, so could the following potentially be updated to read from System.in and then parse the commands?

https://github.com/spring-projects/spring-shell/blob/c4e6cc97fdad6a2981cc4e33d5d303deb1db2799/spring-shell-core/src/main/java/org/springframework/shell/jline/NonInteractiveShellRunner.java#L141

I've got a crude local test and it works with the quickstart example:

public void run(ApplicationArguments args) throws Exception {
    shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE);
    args = mergePipeAndArgs(args);
    List<String> commands = this.commandsFromInputArgs.apply(args);
        ...
}

private ApplicationArguments mergePipeAndArgs(ApplicationArguments args) {
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    String[] mergedArgs = Stream.concat(Arrays.stream(args.getSourceArgs()), stdin.lines())
            .toArray(String[]::new);
    return new DefaultApplicationArguments(mergedArgs);
}
rj93 commented 4 months ago

Did a bit more playing around with the above and it doesn't play very nice piping file contents to it, for example YAML files get parsed broken because of some post processing