Skip to content

Commit 637997c

Browse files
authored
Merge pull request #1050 from Stefterv/feat-command-line
Setup a Command Line Interface
2 parents 732b20c + 036d01e commit 637997c

File tree

6 files changed

+145
-27
lines changed

6 files changed

+145
-27
lines changed

app/build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ sourceSets{
4747

4848
compose.desktop {
4949
application {
50-
mainClass = "processing.app.ui.Start"
50+
mainClass = "processing.app.ProcessingKt"
5151

5252
jvmArgs(*listOf(
5353
Pair("processing.version", rootProject.version),
@@ -97,6 +97,7 @@ compose.desktop {
9797

9898
dependencies {
9999
implementation(project(":core"))
100+
runtimeOnly(project(":java"))
100101

101102
implementation(libs.flatlaf)
102103

@@ -121,6 +122,8 @@ dependencies {
121122
testImplementation(libs.mockitoKotlin)
122123
testImplementation(libs.junitJupiter)
123124
testImplementation(libs.junitJupiterParams)
125+
126+
implementation(libs.clikt)
124127
}
125128

126129
tasks.test {

app/src/processing/app/Processing.kt

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package processing.app
2+
3+
import com.github.ajalt.clikt.command.SuspendingCliktCommand
4+
import com.github.ajalt.clikt.command.main
5+
import com.github.ajalt.clikt.core.Context
6+
import com.github.ajalt.clikt.core.subcommands
7+
import com.github.ajalt.clikt.parameters.arguments.argument
8+
import com.github.ajalt.clikt.parameters.arguments.help
9+
import com.github.ajalt.clikt.parameters.arguments.multiple
10+
import com.github.ajalt.clikt.parameters.options.flag
11+
import com.github.ajalt.clikt.parameters.options.help
12+
import com.github.ajalt.clikt.parameters.options.option
13+
import processing.app.ui.Start
14+
15+
class Processing: SuspendingCliktCommand("processing"){
16+
val version by option("-v","--version")
17+
.flag()
18+
.help("Print version information")
19+
20+
val sketches by argument()
21+
.multiple(default = emptyList())
22+
.help("Sketches to open")
23+
24+
override fun help(context: Context) = "Start the Processing IDE"
25+
override val invokeWithoutSubcommand = true
26+
override suspend fun run() {
27+
if(version){
28+
println("processing-${Base.getVersionName()}-${Base.getRevision()}")
29+
return
30+
}
31+
32+
val subcommand = currentContext.invokedSubcommand
33+
if (subcommand == null) {
34+
Start.main(sketches.toTypedArray())
35+
}
36+
}
37+
}
38+
39+
suspend fun main(args: Array<String>){
40+
Processing()
41+
.subcommands(
42+
LSP(),
43+
LegacyCLI(args)
44+
)
45+
.main(args)
46+
}
47+
48+
class LSP: SuspendingCliktCommand("lsp"){
49+
override fun help(context: Context) = "Start the Processing Language Server"
50+
override suspend fun run(){
51+
try {
52+
// Indirect invocation since app does not depend on java mode
53+
Class.forName("processing.mode.java.lsp.PdeLanguageServer")
54+
.getMethod("main", Array<String>::class.java)
55+
.invoke(null, *arrayOf<Any>(emptyList<String>()))
56+
} catch (e: Exception) {
57+
throw InternalError("Failed to invoke main method", e)
58+
}
59+
}
60+
}
61+
62+
class LegacyCLI(val args: Array<String>): SuspendingCliktCommand( "cli"){
63+
override fun help(context: Context) = "Legacy processing-java command line interface"
64+
65+
val help by option("--help").flag()
66+
val build by option("--build").flag()
67+
val run by option("--run").flag()
68+
val present by option("--present").flag()
69+
val sketch: String? by option("--sketch")
70+
val force by option("--force").flag()
71+
val output: String? by option("--output")
72+
val export by option("--export").flag()
73+
val noJava by option("--no-java").flag()
74+
val variant: String? by option("--variant")
75+
76+
override suspend fun run(){
77+
val cliArgs = args.filter { it != "cli" }
78+
try {
79+
if(build){
80+
System.setProperty("java.awt.headless", "true")
81+
}
82+
// Indirect invocation since app does not depend on java mode
83+
Class.forName("processing.mode.java.Commander")
84+
.getMethod("main", Array<String>::class.java)
85+
.invoke(null, *arrayOf<Any>(cliArgs.toTypedArray()))
86+
} catch (e: Exception) {
87+
throw InternalError("Failed to invoke main method", e)
88+
}
89+
}
90+
}

app/src/processing/app/tools/InstallCommander.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,30 +86,41 @@ public void run() {
8686
PrintWriter writer = PApplet.createWriter(file);
8787
writer.print("#!/bin/sh\n\n");
8888

89-
writer.print("# Prevents processing-java from stealing focus, see:\n" +
90-
"# https://github.com/processing/processing/issues/3996.\n" +
91-
"OPTION_FOR_HEADLESS_RUN=\"\"\n" +
92-
"for ARG in \"$@\"\n" +
93-
"do\n" +
94-
" if [ \"$ARG\" = \"--build\" ]; then\n" +
95-
" OPTION_FOR_HEADLESS_RUN=\"-Djava.awt.headless=true\"\n" +
96-
" fi\n" +
97-
"done\n\n");
98-
99-
String javaRoot = Platform.getContentFile(".").getCanonicalPath();
100-
101-
StringList jarList = new StringList();
102-
addJarList(jarList, new File(javaRoot));
103-
addJarList(jarList, new File(javaRoot, "core/library"));
104-
addJarList(jarList, new File(javaRoot, "modes/java/mode"));
105-
String classPath = jarList.join(":").replaceAll(javaRoot + "\\/?", "");
106-
107-
writer.println("cd \"" + javaRoot + "\" && " +
108-
Platform.getJavaPath().replaceAll(" ", "\\\\ ") +
109-
" -Djna.nosys=true" +
110-
" $OPTION_FOR_HEADLESS_RUN" +
111-
" -cp \"" + classPath + "\"" +
112-
" processing.mode.java.Commander \"$@\"");
89+
var resourcesDir = System.getProperty("compose.application.resources.dir");
90+
if(resourcesDir != null) {
91+
// Gradle based distributable
92+
var appBinary = (resourcesDir
93+
.split("\\.app")[0] + ".app/Contents/MacOS/Processing")
94+
.replaceAll(" ", "\\\\ ");
95+
writer.print(appBinary + " cli $@");
96+
97+
} else {
98+
// Ant based distributable
99+
writer.print("# Prevents processing-java from stealing focus, see:\n" +
100+
"# https://github.com/processing/processing/issues/3996.\n" +
101+
"OPTION_FOR_HEADLESS_RUN=\"\"\n" +
102+
"for ARG in \"$@\"\n" +
103+
"do\n" +
104+
" if [ \"$ARG\" = \"--build\" ]; then\n" +
105+
" OPTION_FOR_HEADLESS_RUN=\"-Djava.awt.headless=true\"\n" +
106+
" fi\n" +
107+
"done\n\n");
108+
109+
String javaRoot = Platform.getContentFile(".").getCanonicalPath();
110+
111+
StringList jarList = new StringList();
112+
addJarList(jarList, new File(javaRoot));
113+
addJarList(jarList, new File(javaRoot, "core/library"));
114+
addJarList(jarList, new File(javaRoot, "modes/java/mode"));
115+
String classPath = jarList.join(":").replaceAll(javaRoot + "\\/?", "");
116+
117+
writer.println("cd \"" + javaRoot + "\" && " +
118+
Platform.getJavaPath().replaceAll(" ", "\\\\ ") +
119+
" -Djna.nosys=true" +
120+
" $OPTION_FOR_HEADLESS_RUN" +
121+
" -cp \"" + classPath + "\"" +
122+
" processing.mode.java.Commander \"$@\"");
123+
}
113124
writer.flush();
114125
writer.close();
115126
file.setExecutable(true);

core/examples/src/main/java/Basic.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
import processing.core.PApplet;
22

3+
import java.io.IOException;
4+
35
public class Basic extends PApplet {
46
public void settings(){
57
size(500, 500);
8+
9+
try {
10+
Runtime.getRuntime().exec("echo Hello World");
11+
} catch (IOException e) {
12+
throw new RuntimeException(e);
13+
}
614
}
715

816
public void draw(){
9-
ellipse(width / 2f, height / 2f, 125f, 125f);
17+
background(255);
18+
fill(0);
19+
ellipse(mouseX, mouseY, 125f, 125f);
20+
println(frameRate);
21+
22+
1023
}
1124

1225

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ lsp4j = { module = "org.eclipse.lsp4j:org.eclipse.lsp4j", version = "0.22.0" }
2727
jsoup = { module = "org.jsoup:jsoup", version = "1.17.2" }
2828
markdown = { module = "com.mikepenz:multiplatform-markdown-renderer-m2", version = "0.31.0" }
2929
markdownJVM = { module = "com.mikepenz:multiplatform-markdown-renderer-jvm", version = "0.31.0" }
30+
clikt = { module = "com.github.ajalt.clikt:clikt", version = "5.0.2" }
3031

3132
[plugins]
3233
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }

java/src/processing/mode/java/lsp/PdeLanguageServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import org.eclipse.lsp4j.services.LanguageClient;
2222

2323

24-
class PdeLanguageServer implements LanguageServer, LanguageClientAware {
24+
public class PdeLanguageServer implements LanguageServer, LanguageClientAware {
2525
Map<File, PdeAdapter> adapters = new HashMap<>();
2626
LanguageClient client = null;
2727
PdeTextDocumentService textDocumentService = new PdeTextDocumentService(this);

0 commit comments

Comments
 (0)