Skip to content

Commit

Permalink
release 1.4.1.
Browse files Browse the repository at this point in the history
1. fix print input param extract error;
2. add compiler util and cellMagic;
3. add read/write/cmd magic.
  • Loading branch information
potoo0 committed Aug 22, 2022
1 parent 4a0e1dc commit f259b73
Show file tree
Hide file tree
Showing 14 changed files with 557 additions and 22 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,4 @@ jobs:
with:
body_path: UPGRADE.md
files: |
README.md
build/distributions/ijava-1.4.0.zip
build/distributions/ijava-latest.zip
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ features and magics:
![timeout](docs/img/line-magic-list.png)
* add `time` cell magic
![timeout](docs/img/cell-magic-time.png)
* add `compile` cellMagic (make sure `--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED` in env *
IJAVA_COMPILER_OPTS*)
![compile](docs/img/compile-cell-magic.png)
* add `read/write` cell/body magic
![r-w](docs/img/read-write-line-magic.png)
![r-w](docs/img/write-cell-magic.png)
* add `cmd` line magic
![cmd](docs/img/cmd-line-magic.png)

[//]: # ([![badge](https://img.shields.io/badge/launch-binder-E66581.svg?logo=data:image/png;base64,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)](https://mybinder.org/v2/gh/SpencerPark/ijava-binder/master) [![badge](https://img.shields.io/badge/launch-binder%20lab-579ACA.svg?logo=data:image/png;base64,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)](https://mybinder.org/v2/gh/SpencerPark/ijava-binder/master?urlpath=lab))

Expand Down
20 changes: 11 additions & 9 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Upgrade Note:

* Upgrade to jdk 17 and gradle 7.3.3
* Print with variable name or source
![timeout](docs/img/print-with-var-name.png)
* add `print` function and `printerPrefix` line magic
![timeout](docs/img/print-func-line-magic.png)
* add `list` line magic
![timeout](docs/img/line-magic-list.png)
* add `time` cell magic
![timeout](docs/img/cell-magic-time.png)
* Fix `print` input parameter extraction error in code blocks that are called multiple times;
* add `RuntimeCompiler` util;
* add `compile` cellMagic (make sure `--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED` in env *
IJAVA_COMPILER_OPTS*)
![compile](docs/img/compile-cell-magic.png)
* add `read/write` cell/body magic
![r-w](docs/img/read-write-line-magic.png)
![r-w](docs/img/write-cell-magic.png)
* add `cmd` line magic
![cmd](docs/img/cmd-line-magic.png)

4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ plugins {
}

group = 'io.github.spencerpark'
version = '1.4.0'
version = '1.4.1'

repositories {
mavenLocal()
Expand Down Expand Up @@ -98,6 +98,8 @@ licenseReport {

// pack up
tasks.register('packDist', Zip) {
archiveFileName = project.name + "-latest.zip"

from(layout.buildDirectory.dir("resources/main")) {
include "install.py"
}
Expand Down
Binary file added docs/img/cmd-line-magic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/compile-cell-magic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/read-write-line-magic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/write-cell-magic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/main/java/io/github/spencerpark/ijava/JavaKernel.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public JavaKernel() {
magics.registerMagics(new PrinterMagics());
magics.registerMagics(new MagicsTool());
magics.registerMagics(new TimeItMagics());
magics.registerMagics(new CompilerMagics(this::addToClasspath));

this.languageInfo = new LanguageInfo.Builder("Java")
.version(Runtime.version().toString())
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/io/github/spencerpark/ijava/magics/CompilerMagics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 ${author}
*
* 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.ijava.IJava;
import io.github.spencerpark.ijava.JavaKernel;
import io.github.spencerpark.ijava.execution.CodeEvaluator;
import io.github.spencerpark.ijava.utils.RuntimeCompiler;
import io.github.spencerpark.jupyter.kernel.magic.registry.CellMagic;
import io.github.spencerpark.jupyter.kernel.util.GlobFinder;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CompilerMagics {
private static final List<String> COMMENT_PATTERNS = List.of("/\\*(.|\\s)*?\\*/", "//.*\\n*");
private static final Pattern PACKAGE_PATTERN = Pattern.compile("\\s*package\\s+(?<package>\\w+(\\.\\w+){0,100})\\s*");

private final Consumer<String> addToClasspath;

private CodeEvaluator evaluator;

public CompilerMagics(Consumer<String> addToClasspath) {
this.addToClasspath = addToClasspath;
}

@CellMagic(aliases = {"compile"})
public void compile(List<String> args, String body) {
if (args.isEmpty()) throw new RuntimeException("Please specify *Class Canonical Name* in args!");

// 1. autofill package base on class canonical name
String bodyCopy = body;
for (String pattern : COMMENT_PATTERNS) bodyCopy = bodyCopy.replaceAll(pattern, "");
Matcher matcher = PACKAGE_PATTERN.matcher(bodyCopy);
String clzCanonicalName = args.get(0);
String[] namePart = clzCanonicalName.split("\\.");
if (!matcher.find()) body = String.format("package %s;", namePart[namePart.length - 1]) + body;

// 2. build
RuntimeCompiler.compile(clzCanonicalName, body, buildCompilerOptions(), true);

// 3. add to classpath
// todo hot-reload class
GlobFinder resolver = new GlobFinder(namePart[0]);
try {
resolver.computeMatchingPaths().forEach(path -> this.addToClasspath.accept(path.getParent().toAbsolutePath().toString()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public RuntimeCompiler.CompileOptions buildCompilerOptions() {
RuntimeCompiler.CompileOptions compileOptions = new RuntimeCompiler.CompileOptions();
try {
if (evaluator == null) getEvaluator();
Object result = evaluator.eval("""
import java.lang.invoke.MethodHandles;
ClassLoader cl = MethodHandles.lookup().lookupClass().getClassLoader();
StringBuilder classpath = new StringBuilder();
String separator = System.getProperty("path.separator");
String cp = System.getProperty("java.class.path");
String mp = System.getProperty("jdk.module.path");
if (cp != null && !"".equals(cp)) classpath.append(cp);
if (mp != null && !"".equals(mp)) classpath.append(mp);
if (cl instanceof URLClassLoader) {
for (URL url : ((URLClassLoader) cl).getURLs()) {
if (classpath.length() > 0) classpath.append(separator);
if ("file".equals(url.getProtocol())) classpath.append(new File(url.toURI()));
}
}
classpath.toString()
""");
return compileOptions.options("-classpath", (String) result);
} catch (Exception e) {
System.err.println("get jshell instance class path error. keep default class path.");
}
return compileOptions;
}

public void getEvaluator() {
try {
JavaKernel kernel = IJava.getKernelInstance();
Field field = kernel.getClass().getDeclaredField("evaluator");
field.setAccessible(true);
evaluator = (CodeEvaluator) field.get(kernel);
} catch (Exception e) {
throw new RuntimeException("Compiler get JShell evaluator instance error." + e.getMessage());
}
}
}
94 changes: 94 additions & 0 deletions src/main/java/io/github/spencerpark/ijava/magics/MagicsTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,28 @@
*/
package io.github.spencerpark.ijava.magics;

import io.github.spencerpark.ijava.IJava;
import io.github.spencerpark.ijava.JavaKernel;
import io.github.spencerpark.ijava.execution.CodeEvaluator;
import io.github.spencerpark.jupyter.kernel.magic.registry.CellMagic;
import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagic;
import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagicFunction;
import io.github.spencerpark.jupyter.kernel.magic.registry.Magics;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MagicsTool {
private static final String HIGHLIGHT_PATTERN = "\u001B[36m%s\u001B[0m";

private CodeEvaluator evaluator;

@LineMagic
public void listLineMagic(List<String> args) {
Expand Down Expand Up @@ -65,6 +74,80 @@ public void listMagic(List<String> args) {
listCellMagic(Collections.emptyList());
}

@LineMagic(value = "cmd")
public void runCommand(List<String> args) throws IOException {
if (args.isEmpty()) return;
Process proc = Runtime.getRuntime().exec(args.toArray(new String[0]));

String s;
try (InputStreamReader inputStreamReader = new InputStreamReader(proc.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
}
try (InputStreamReader inputStreamReader = new InputStreamReader(proc.getErrorStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
while ((s = bufferedReader.readLine()) != null) {
System.err.println(s);
}
}
}

@LineMagic(value = "read")
public String readFromFile(List<String> args) throws IOException {
if (args.isEmpty()) {
System.out.println("""
-h/--help for help.
help:
example:
1. `String content = %read filename` will read file and return for content.
""");
return null;
}
return String.join("\n", Files.readAllLines(Path.of(args.get(0))));
}

@LineMagic(value = "write")
public void writeToFile(List<String> args) throws IOException {
if (args.isEmpty()) {
System.out.println("""
-h/--help for help.
help:
example:
1. `%write variable filename` will read variable's write to file.
2. `%write variable` will read variable's write to temp file.
""");
return;
}

if (evaluator == null) getEvaluator();
Object content;
try {
content = evaluator.eval(args.get(0));
} catch (Exception e) {
throw new RuntimeException("eval variable `" + args.get(0) + "` error, variable not found or illegal express!");
}

List<String> argsLast = args.size() > 1 ? Collections.singletonList(args.get(1)) : Collections.emptyList();
writeToFile(argsLast, content.toString());
}

@CellMagic(value = "write")
public void writeToFile(List<String> args, String body) throws IOException {
String fileName = args.isEmpty()
? Files.createTempFile("jshell-", ".tmp").toAbsolutePath().toString()
: args.get(0);
File file = new File(fileName);
if (file.getParentFile() != null && !file.getParentFile().exists() && !file.getParentFile().mkdirs())
throw new IOException("Cannot create parent folder: " + file.getParentFile());
try (FileWriter writer = new FileWriter(file)) {
writer.write(body);
writer.flush();
}
System.out.printf("Write to %s success.%n", String.format(HIGHLIGHT_PATTERN, file.getAbsolutePath()));
}

@SuppressWarnings("unchecked")
private Collection<String> getMagicsName(Magics magics, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Field field = magics.getClass().getDeclaredField(fieldName);
Expand All @@ -75,4 +158,15 @@ private Collection<String> getMagicsName(Magics magics, String fieldName) throws
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.joining(", "))))
.values();
}

public void getEvaluator() {
try {
JavaKernel kernel = IJava.getKernelInstance();
Field field = kernel.getClass().getDeclaredField("evaluator");
field.setAccessible(true);
evaluator = (CodeEvaluator) field.get(kernel);
} catch (Exception e) {
throw new RuntimeException("Compiler get JShell evaluator instance error." + e.getMessage());
}
}
}
Loading

0 comments on commit f259b73

Please sign in to comment.