diff --git a/docs/magics.md b/docs/magics.md index f6bf8ea..7364746 100644 --- a/docs/magics.md +++ b/docs/magics.md @@ -124,4 +124,14 @@ The cell magic is designed to make it very simple to copy and paste from any REA jupyter-jvm-basekernel 2.0.0-SNAPSHOT - ``` \ No newline at end of file + ``` + +### exec + +Allow user to execute system program in jupyter notebook. + +###### Line magic + +* **aliases**: `system` +* **arguments**: + * _varargs_ list of external program and its command line arguments to be executed \ No newline at end of file diff --git a/src/main/java/io/github/spencerpark/ijava/JavaKernel.java b/src/main/java/io/github/spencerpark/ijava/JavaKernel.java index b61d3af..13f8eac 100644 --- a/src/main/java/io/github/spencerpark/ijava/JavaKernel.java +++ b/src/main/java/io/github/spencerpark/ijava/JavaKernel.java @@ -25,6 +25,7 @@ import io.github.spencerpark.ijava.execution.*; import io.github.spencerpark.ijava.magics.ClasspathMagics; +import io.github.spencerpark.ijava.magics.ExecMagics; import io.github.spencerpark.ijava.magics.MavenResolver; import io.github.spencerpark.jupyter.kernel.BaseKernel; import io.github.spencerpark.jupyter.kernel.LanguageInfo; @@ -95,6 +96,7 @@ public JavaKernel() { this.magics.registerMagics(this.mavenResolver); this.magics.registerMagics(new ClasspathMagics(this::addToClasspath)); this.magics.registerMagics(new Load(List.of(".jsh", ".jshell", ".java", ".ijava"), this::eval)); + this.magics.registerMagics(new ExecMagics()); this.languageInfo = new LanguageInfo.Builder("Java") .version(Runtime.version().toString()) diff --git a/src/main/java/io/github/spencerpark/ijava/magics/ExecMagics.java b/src/main/java/io/github/spencerpark/ijava/magics/ExecMagics.java new file mode 100644 index 0000000..fd2d98a --- /dev/null +++ b/src/main/java/io/github/spencerpark/ijava/magics/ExecMagics.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Spencer Park + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.github.spencerpark.ijava.magics; + +import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagic; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Scanner; + +public class ExecMagics { + + @LineMagic(aliases = "system") + public void exec(List args) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + pb.command(args); + pb.redirectErrorStream(true); + Process process = pb.start(); + + try (Scanner scanner = new Scanner(process.getInputStream(), StandardCharsets.UTF_8)) { + while (scanner.hasNext()) { + System.out.println(scanner.nextLine()); + } + } + } +} \ No newline at end of file