diff --git a/pom.xml b/pom.xml index 9c8ea7d..967fa3b 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,12 @@ controlsfx 8.40.14 + + + info.picocli + picocli + 3.9.5 + org.projectlombok diff --git a/src/main/java/me/coley/j2h/Java2Html.java b/src/main/java/me/coley/j2h/Java2Html.java index 3f2d849..7ec861e 100644 --- a/src/main/java/me/coley/j2h/Java2Html.java +++ b/src/main/java/me/coley/j2h/Java2Html.java @@ -7,7 +7,7 @@ import javafx.geometry.Orientation; import javafx.scene.Scene; import javafx.scene.control.*; -import javafx.scene.input.MouseButton; +import javafx.scene.input.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.text.Font; @@ -20,16 +20,18 @@ import me.coley.j2h.config.*; import me.coley.j2h.config.model.*; import me.coley.j2h.ui.RuleCell; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.controlsfx.validation.ValidationSupport; +import picocli.CommandLine; +import picocli.CommandLine.Option; import javax.xml.bind.JAXBException; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.Collections; -import java.util.Optional; +import java.util.*; +import java.util.concurrent.Callable; import static java.nio.charset.StandardCharsets.UTF_8; import static org.controlsfx.validation.Validator.createEmptyValidator; @@ -40,20 +42,33 @@ * * @author Matt */ -public class Java2Html extends Application { +public class Java2Html extends Application implements Callable { // Base values private static String css = ""; private static String js = ""; + // Command line options/args + @Option(names = {"-c", "--config"}, description = "Config to with languages and themes") + private File clConfig; + @Option(names = {"-l", "--language"}, description = "Language in config to use for parsing") + private String clLanguage; + @Option(names = {"-t", "--theme"}, description = "Theme in config to use for styling") + private String clTheme; + @Option(names = {"-v", "--clipboard"}, description = "Copy output to clipboard") + private boolean clClipboard; + @Option(names = {"-o", "--out"}, description = "The file to output converted HTML to") + private File clOutput; + @CommandLine.Parameters(index = "0", description = "The file to convert to styled HTML") + private File clInput; // Controls - private final WebView browser = new WebView(); - private final TextArea txtInput = new TextArea(); - private final TextArea txtHTML = new TextArea(); - private final TextArea txtCSS = new TextArea(); - private final TextArea txtJS = new TextArea(); + private WebView browser; + private TextArea txtInput; + private TextArea txtHTML; + private TextArea txtCSS; + private TextArea txtJS; // Misc layout & stuff - private final Menu mnLang = new Menu("Language"); - private final Menu mnTheme = new Menu("Theme"); - private final BorderPane patternsPane = new BorderPane(); + private Menu mnLang; + private Menu mnTheme; + private BorderPane patternsPane; private Stage stage; private boolean previewLock; // Config @@ -65,13 +80,76 @@ public static void main(String[] args) { css = IOUtils.toString(Java2Html.class.getResourceAsStream("/code.css"), UTF_8); js = IOUtils.toString(Java2Html.class.getResourceAsStream("/code.js"), UTF_8); } catch(Exception e) { - System.err.println("Failed to load default resources: css/js"); e.printStackTrace(); + System.err.println("Failed to load default resources: css/js"); System.exit(-1); } + // Check command line values + invokeCmd(args); + // Invoke GUI if command line doesn't terminate launch(args); } + private static void invokeCmd(String[] args) { + // Disable System.err so that GUI invokes don't print command-line usage + PrintStream ps = System.err; + System.setErr(new PrintStream(new ByteArrayOutputStream())); + // Call CLI + // If the input argument is missing, it won't even be invoked. + CommandLine.call(new Java2Html(),ps, args); + // Reset err + System.setErr(ps); + } + + @Override + public Void call() { + try { + // Verification + if (clOutput == null && !clClipboard) { + System.out.println("No output for converted content"); + System.exit(0); + } + if (!clInput.exists()) { + System.out.println("Input file does not exist"); + System.exit(0); + } + // Setup + Configuration configuration = clConfig == null ? Importer.importDefault() : Importer.importFromFile(clConfig.getAbsolutePath()); + Language language = clLanguage == null ? configuration.getLanguages().get(0) : configuration.findLanguage(clLanguage); + Theme theme = clTheme == null ? language.getThemes().get(0) : language.findTheme(clTheme); + helper = new ConfigHelper(configuration, language, theme); + // Input reading & parsing + String text = FileUtils.readFileToString(clInput, UTF_8); + String converted = helper.convert(text); + // Output + Platform.runLater(() -> { + if(clClipboard) { + Clipboard clip = Clipboard.getSystemClipboard(); + clip.clear(); + Map content = new HashMap<>(); + content.put(DataFormat.PLAIN_TEXT, converted); + clip.setContent(content); + } + if(clOutput != null) { + try { + FileUtils.write(clOutput, converted, UTF_8); + } catch(IOException e) { + System.out.println("Failed to write to file: " + clOutput); + System.out.println(e.getMessage()); + } + } + Platform.exit(); + }); + } catch(JAXBException e) { + System.out.println("Failed to parse config: " + clConfig); + System.out.println(e.getMessage()); + } catch(IOException e) { + System.out.println("Failed to read from config: " + clConfig); + System.out.println(e.getMessage()); + } + return null; + } + @Override public void start(Stage stage) { this.stage = stage; @@ -87,6 +165,14 @@ public void start(Stage stage) { "The default configuration file failed to be read.", "Please ensure the default configuration file is properly formatted."); } + browser = new WebView(); + txtInput = new TextArea(); + txtHTML = new TextArea(); + txtCSS = new TextArea(); + txtJS = new TextArea(); + mnLang = new Menu("Language"); + mnTheme = new Menu("Theme"); + patternsPane = new BorderPane(); // Inputs txtInput.setText("class Example { \n\t// put source code here\n}"); txtInput.setFont(Font.font("monospace")); diff --git a/src/main/java/me/coley/j2h/config/Importer.java b/src/main/java/me/coley/j2h/config/Importer.java index 25de062..1e299d3 100644 --- a/src/main/java/me/coley/j2h/config/Importer.java +++ b/src/main/java/me/coley/j2h/config/Importer.java @@ -1,6 +1,7 @@ package me.coley.j2h.config; import me.coley.j2h.config.model.Configuration; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import javax.xml.bind.*; @@ -34,7 +35,7 @@ public final class Importer { public static Configuration importFromFile(String path) throws JAXBException, IOException { JAXBContext context = JAXBContext.newInstance(Configuration.class); Unmarshaller um = context.createUnmarshaller(); - return (Configuration) um.unmarshal(new StringReader(readFile(path, UTF_8))); + return (Configuration) um.unmarshal(new StringReader(FileUtils.readFileToString(new File(path), UTF_8))); } /** @@ -77,20 +78,4 @@ public static Configuration importDefault() throws JAXBException, IOException { } throw new IOException("Default configuration location unknown"); } - - /** - * @param path - * Path to file. - * @param encoding - * File encoding. - * - * @return Content of file. - * - * @throws IOException - * Thrown if the file could not be read from. - */ - private static String readFile(String path, Charset encoding) throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } } diff --git a/src/main/java/me/coley/j2h/config/model/Configuration.java b/src/main/java/me/coley/j2h/config/model/Configuration.java index ce0b10e..1c122a2 100644 --- a/src/main/java/me/coley/j2h/config/model/Configuration.java +++ b/src/main/java/me/coley/j2h/config/model/Configuration.java @@ -32,10 +32,11 @@ public void addLanguage(Language language) { * @param name * Language identifier. * - * @return Languages matching the given name. + * @return Language matching the given name. */ - public Language findByName(String name) { - return languages.stream().filter(l -> l.getName().equalsIgnoreCase(name)).findFirst() - .orElse(null); + public Language findLanguage(String name) { + return languages.stream() + .filter(l -> l.getName().equalsIgnoreCase(name)) + .findFirst().orElse(null); } } diff --git a/src/main/java/me/coley/j2h/config/model/Language.java b/src/main/java/me/coley/j2h/config/model/Language.java index 6504f07..d719fff 100644 --- a/src/main/java/me/coley/j2h/config/model/Language.java +++ b/src/main/java/me/coley/j2h/config/model/Language.java @@ -64,4 +64,16 @@ public void addRule(Rule rule) { public void addTheme(Theme theme) { this.themes.add(theme); } + + /** + * @param name + * Theme identifier. + * + * @return Theme matching the given name. + */ + public Theme findTheme(String name) { + return themes.stream() + .filter(t -> t.getName().equalsIgnoreCase(name)) + .findFirst().orElse(null); + } }