jbangdev / jbang

Unleash the power of Java - JBang Lets Students, Educators and Professional Developers create, edit and run self-contained source-only Java programs with unprecedented ease.
https://jbang.dev
MIT License
1.37k stars 153 forks source link

feat: Java API for running JBang #1814

Open dsyer opened 1 week ago

dsyer commented 1 week ago

I would like to be able to use JBang to run another JBang command (so I can do some processing of user input and delegate the result). It's quite hard right now as you have to try and scrape the generated command line from stderr, unless I'm missing something. E.g. this works for me:

public class runner {

    private static final String RUN_PREFIX = "] run: ";

    public static void main(String[] args) throws IOException {
        CommandLine cli = JBang.getCommandLine();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        var err = System.err;
        System.setErr(new PrintStream(out));
        boolean verbose = Util.isVerbose();
        Util.setVerbose(true);
        int result = cli.execute(args);
        System.setErr(err);
        Util.setVerbose(verbose);
        String cmd = out.toString().trim();
        if (result == 255 && cmd.length() > 0 && cmd.indexOf(RUN_PREFIX) > 0) {
            cmd = cmd.substring(cmd.lastIndexOf(RUN_PREFIX) + 7);
            // System.out.println("Run: " + cmd);
            Process process = new ProcessBuilder(cmd.toString().split("\\s+")).inheritIO().start();
            try {
                process.waitFor();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

}

but it's kind of scary, and you can't avoid the command also being printed to stdout.

nnsns commented 1 week ago

Also it will be nice to have an option to pass to another JBang command an object from main JBang/Java app.

For example, the main application can prepare an object for further processing and logger and pass these 2 objects to the spawned JBang command.

Ideally, it would be great to have full communication between the two processes, including callback capability.

dsyer commented 1 week ago

If #1811 is merged we could implement a JBang launcher API by referring to System.getenv("JBANG_LAUNCH_CMD"). That might be cleaner. Would be good to have access to the original command line, or the options at least, but I'm not sure it would allow communication between the two processes.

maxandersen commented 1 week ago

There can't be two way communication - jbang exits after printing the command to execute.

Having an API to find and get access to jbang and it's features makes sense.