From 8a4ea97a2edee8a530bf610ec21473bfff645000 Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Tue, 18 Nov 2025 23:44:43 +0530 Subject: [PATCH 1/3] fix(cli): support sketches with custom main file names Previously, the CLI only accepted sketches where the main .pde file matched the sketch folder name (e.g., sketch/sketch.pde). This caused issues when users renamed their main file in the IDE, which stores the custom filename in sketch.properties. Now the CLI checks sketch.properties for a 'main' property before falling back to the default naming convention, matching the IDE's behavior implemented in Sketch.findMain(). Fixes #1219 --- java/src/processing/mode/java/Commander.java | 20 ++++- .../processing/mode/java/CommanderTest.java | 89 +++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 java/test/processing/mode/java/CommanderTest.java diff --git a/java/src/processing/mode/java/Commander.java b/java/src/processing/mode/java/Commander.java index b13c1a5f11..d9618578f3 100644 --- a/java/src/processing/mode/java/Commander.java +++ b/java/src/processing/mode/java/Commander.java @@ -32,6 +32,7 @@ import processing.app.Platform; import processing.app.Preferences; import processing.app.RunnerListener; +import processing.app.Settings; import processing.app.Sketch; import processing.utils.SketchException; import processing.app.Util; @@ -145,7 +146,24 @@ public Commander(String[] args) { if (!sketchFolder.exists()) { complainAndQuit(sketchFolder + " does not exist.", false); } - File pdeFile = new File(sketchFolder, sketchFolder.getName() + ".pde"); + + // Check for main file in sketch.properties first, then fall back to default + File pdeFile = null; + try { + Settings props = new Settings(new File(sketchFolder, "sketch.properties")); + String mainFileName = props.get("main"); + if (mainFileName != null) { + pdeFile = new File(sketchFolder, mainFileName); + } + } catch (IOException e) { + // sketch.properties doesn't exist or couldn't be read, will use default + } + + // Fall back to default naming convention if no custom main file specified + if (pdeFile == null || !pdeFile.exists()) { + pdeFile = new File(sketchFolder, sketchFolder.getName() + ".pde"); + } + if (!pdeFile.exists()) { complainAndQuit("Not a valid sketch folder. " + pdeFile + " does not exist.", true); } diff --git a/java/test/processing/mode/java/CommanderTest.java b/java/test/processing/mode/java/CommanderTest.java new file mode 100644 index 0000000000..263f8c93ba --- /dev/null +++ b/java/test/processing/mode/java/CommanderTest.java @@ -0,0 +1,89 @@ +package processing.mode.java; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import processing.app.Settings; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; + +import static org.junit.Assert.*; + + +public class CommanderTest { + + private File tempSketchFolder; + + @Before + public void setUp() throws IOException { + tempSketchFolder = Files.createTempDirectory("sketch_test").toFile(); + } + + @After + public void tearDown() { + if (tempSketchFolder != null && tempSketchFolder.exists()) { + deleteDirectory(tempSketchFolder); + } + } + + @Test + public void testSketchWithDefaultMainFile() throws IOException { + String sketchName = tempSketchFolder.getName(); + File mainFile = new File(tempSketchFolder, sketchName + ".pde"); + + try (FileWriter writer = new FileWriter(mainFile)) { + writer.write("void setup() {}\nvoid draw() {}"); + } + + assertTrue("Default main file should exist", mainFile.exists()); + } + + @Test + public void testSketchWithCustomMainFile() throws IOException { + File customMainFile = new File(tempSketchFolder, "custom_main.pde"); + try (FileWriter writer = new FileWriter(customMainFile)) { + writer.write("void setup() {}\nvoid draw() {}"); + } + + File propsFile = new File(tempSketchFolder, "sketch.properties"); + Settings props = new Settings(propsFile); + props.set("main", "custom_main.pde"); + props.save(); + + assertTrue("Custom main file should exist", customMainFile.exists()); + assertTrue("sketch.properties should exist", propsFile.exists()); + + Settings readProps = new Settings(propsFile); + assertEquals("custom_main.pde", readProps.get("main")); + } + + @Test + public void testSketchPropertiesMainProperty() throws IOException { + File propsFile = new File(tempSketchFolder, "sketch.properties"); + Settings props = new Settings(propsFile); + props.set("main", "my_sketch.pde"); + props.save(); + + Settings readProps = new Settings(propsFile); + String mainFile = readProps.get("main"); + + assertEquals("Main property should match", "my_sketch.pde", mainFile); + } + + private void deleteDirectory(File directory) { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + file.delete(); + } + } + } + directory.delete(); + } +} From 62e5c20bb2e4f76c846b3f9fc0dd17ce37ac2c92 Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Wed, 3 Dec 2025 22:58:03 +0530 Subject: [PATCH 2/3] test: add CLI test for custom main file support Added testSketchWithCustomMainFile() to CLITest.kt as requested by maintainer. This test provides a placeholder for manual testing of sketches with custom main files specified in sketch.properties. Follows the same pattern as existing CLI tests (testLSP, testLegacyCLI) and is intended to be run manually in IntelliJ IDEA. --- app/test/processing/app/CLITest.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/test/processing/app/CLITest.kt b/app/test/processing/app/CLITest.kt index 2bd8cc81e7..89cc0a9211 100644 --- a/app/test/processing/app/CLITest.kt +++ b/app/test/processing/app/CLITest.kt @@ -25,6 +25,17 @@ class CLITest { runCLIWithArguments("cli --help") } + @Test + fun testSketchWithCustomMainFile(){ + // This test requires manual setup: + // 1. Create a sketch folder with a custom main file (e.g., sketch/custom.pde) + // 2. Add sketch.properties with: main=custom.pde + // 3. Update the path below to your test sketch + // 4. Run this test in IntelliJ IDEA + // Uncomment and modify the path below to test: + // runCLIWithArguments("cli --sketch=path/to/your/test/sketch --run") + } + /* This function runs the CLI with the given arguments. */ From 0ae47898b69868e3120309ec95d2d2c514d8a2c7 Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Sun, 7 Dec 2025 10:40:19 +0530 Subject: [PATCH 3/3] test: convert to automated CLI test with temp directory Converted testSketchWithCustomMainFile() from manual to automated test. Now creates a temporary sketch folder with custom main file and sketch.properties, then tests the CLI build command. Follows the pattern from SchemaTest.kt using Files.createTempDirectory() and automatic cleanup. --- app/test/processing/app/CLITest.kt | 34 ++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/app/test/processing/app/CLITest.kt b/app/test/processing/app/CLITest.kt index 89cc0a9211..6ae04e46c9 100644 --- a/app/test/processing/app/CLITest.kt +++ b/app/test/processing/app/CLITest.kt @@ -1,6 +1,7 @@ package processing.app import java.io.File +import java.nio.file.Files import kotlin.test.Test /* @@ -27,13 +28,32 @@ class CLITest { @Test fun testSketchWithCustomMainFile(){ - // This test requires manual setup: - // 1. Create a sketch folder with a custom main file (e.g., sketch/custom.pde) - // 2. Add sketch.properties with: main=custom.pde - // 3. Update the path below to your test sketch - // 4. Run this test in IntelliJ IDEA - // Uncomment and modify the path below to test: - // runCLIWithArguments("cli --sketch=path/to/your/test/sketch --run") + val tempDir = Files.createTempDirectory("cli_custom_main_test") + try { + val sketchFolder = tempDir.resolve("TestSketch").toFile() + sketchFolder.mkdirs() + + // Create custom main file (not matching folder name) + val customMain = File(sketchFolder, "custom_main.pde") + customMain.writeText(""" + void setup() { + println("Custom main file test"); + } + + void draw() { + exit(); + } + """.trimIndent()) + + // Create sketch.properties with custom main + val propsFile = File(sketchFolder, "sketch.properties") + propsFile.writeText("main=custom_main.pde") + + // Test with CLI + runCLIWithArguments("cli --sketch=${sketchFolder.absolutePath} --build") + } finally { + tempDir.toFile().deleteRecursively() + } } /*