diff --git a/build.gradle b/build.gradle index f92b22205..b94a556d0 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ dependencies { implementation 'com.offbytwo:docopt:0.6.0.20150202' implementation 'info.picocli:picocli:4.1.4' + //implementation 'io.quarkus.qute:qute-core:1.1.0.Final' implementation("com.jcabi:jcabi-aether:0.10.1") { exclude group: "org.hibernate", module: "hibernate-validator" diff --git a/readme.adoc b/readme.adoc index 259393a40..10599b968 100644 --- a/readme.adoc +++ b/readme.adoc @@ -79,6 +79,10 @@ chmod +x helloworld.java There are experimental support to run `.jsh` via `jshell`. The advantage of `jshell` is that you do not need to have a class or static main method, downside is that at least for now you have no way to read the command line arguments. +## Getting started + +To get started you can run `jbang --init helloworld.java` and a simple java class with a static main is generated. + ## Declare dependencies with `//DEPS` If you want to write real scripts you will want to use some java libraries. diff --git a/src/main/java/dk/xam/jbang/ExitException.java b/src/main/java/dk/xam/jbang/ExitException.java index afd6e7a2f..b661c3acb 100644 --- a/src/main/java/dk/xam/jbang/ExitException.java +++ b/src/main/java/dk/xam/jbang/ExitException.java @@ -11,6 +11,11 @@ public ExitException(int status) { this.status = status; } + public ExitException(int status, Exception cause) { + super(cause); + this.status = status; + } + public int getStatus() { return status; } diff --git a/src/main/java/dk/xam/jbang/Main.java b/src/main/java/dk/xam/jbang/Main.java index d0db22f18..0ed0f744f 100644 --- a/src/main/java/dk/xam/jbang/Main.java +++ b/src/main/java/dk/xam/jbang/Main.java @@ -3,9 +3,8 @@ import static java.lang.System.*; import static picocli.CommandLine.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; +import java.io.*; +import java.nio.file.Files; import java.util.*; import java.util.concurrent.Callable; import java.util.stream.Collectors; @@ -34,6 +33,9 @@ public class Main implements Callable { @Parameters(index = "1..*", arity = "0..*", description = "Parameters to pass on to the script") List params = new ArrayList(); + @Option(names = {"--init"}, description = "Init script with a java class useful for scripting.") + boolean initScript; + void info(String msg) { spec.commandLine().getErr().println(msg); } @@ -65,7 +67,7 @@ static CommandLine getCommandLine() { } @Override - public Integer call() throws FileNotFoundException { + public Integer call() throws IOException { if (helpRequested) { spec.commandLine().usage(err); @@ -75,13 +77,46 @@ public Integer call() throws FileNotFoundException { quit(0); } - String cmdline = generateCommandLine(); + if (initScript) { + var f = new File(scriptOrFile); + if (f.exists()) { + warn("File " + f + " already exists. Will not initialize."); + } else { + // Use try-with-resource to get auto-closeable writer instance + try (BufferedWriter writer = Files.newBufferedWriter(f.toPath())) { + String result = renderInitClass(f); + writer.write(result); + } + } - out.println(cmdline); + } else { + String cmdline = generateCommandLine(); + out.println(cmdline); + } return 0; } + static String initTemplate = "//usr/bin/env jbang \"$0\" \"$@\" ; exit $?\n" + + "// //DEPS \n" + "\n" + "import static java.lang.System.*;\n" + "\n" + + "public class {className} {\n" + "\n" + " public static void main(String... args) {\n" + + " out.println(\"Hello World\");\n" + " }\n" + "}"; + + String renderInitClass(File f) { + + return initTemplate.replace("{className}", getBaseName(f.getName())); + + } + + public static String getBaseName(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1) { + return fileName; + } else { + return fileName.substring(0, index); + } + } + String generateCommandLine() throws FileNotFoundException { prepareScript = prepareScript(scriptOrFile); diff --git a/src/test/java/dk/xam/jbang/TestInit.java b/src/test/java/dk/xam/jbang/TestInit.java new file mode 100644 index 000000000..fbaa8e4d2 --- /dev/null +++ b/src/test/java/dk/xam/jbang/TestInit.java @@ -0,0 +1,22 @@ +package dk.xam.jbang; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +public class TestInit { + + @Test + void testInit() { + + var m = new Main(); + + String s = m.renderInitClass(new File("test.java")); + + assertThat(s, not(containsString("NOT_FOUND"))); + + } +} diff --git a/src/test/java/dk/xam/jbang/TestMain.java b/src/test/java/dk/xam/jbang/TestMain.java index ed80f443e..77770a4dd 100644 --- a/src/test/java/dk/xam/jbang/TestMain.java +++ b/src/test/java/dk/xam/jbang/TestMain.java @@ -86,6 +86,6 @@ void testDependencies() throws FileNotFoundException { assertThat(result, not(containsString(" "))); assertThat(result, containsString("classpath")); assertThat(result, containsString("log4j")); - } + } }