Implement CLI --export-svg parameter for instant SVG export

Co-authored-by: enaut <290005+enaut@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-01-01 20:40:06 +00:00
parent d85a9c7d26
commit c806570156
2 changed files with 72 additions and 24 deletions

View File

@ -123,7 +123,7 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
quote! { quote! {
#[macroquad::main(#window_title)] #[macroquad::main(#window_title)]
async fn main() { async fn main() {
// Parse command-line arguments for SVG export // Parse command-line arguments for SVG export FIRST (before any graphics init)
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let mut export_svg_path: Option<String> = None; let mut export_svg_path: Option<String> = None;
@ -136,22 +136,21 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
i += 1; i += 1;
} }
let mut turtle = turtle_lib::create_turtle_plan(); // Handle SVG export mode (execute instantly without rendering)
// Call the user's function with the turtle
#fn_name(&mut turtle);
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
// Handle SVG export if requested
if let Some(filename) = export_svg_path { if let Some(filename) = export_svg_path {
#[cfg(feature = "svg")] #[cfg(feature = "svg")]
{ {
let mut turtle = turtle_lib::create_turtle_plan();
#fn_name(&mut turtle);
// Create app and execute instantly
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
// Set instant speed to execute all commands immediately // Set instant speed to execute all commands immediately
app.set_all_turtles_speed(turtle_lib::AnimationSpeed::Instant(1000)); app.set_all_turtles_speed(turtle_lib::AnimationSpeed::Instant(1000));
// Execute all commands instantly // Execute all commands instantly (no rendering needed)
while !app.all_animations_complete() { while !app.all_animations_complete() {
app.update(); app.update();
} }
@ -176,7 +175,15 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
} }
} }
// Normal rendering loop // Normal rendering mode (with window)
let mut turtle = turtle_lib::create_turtle_plan();
// Call the user's function with the turtle
#fn_name(&mut turtle);
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
loop { loop {
macroquad::prelude::clear_background(macroquad::prelude::WHITE); macroquad::prelude::clear_background(macroquad::prelude::WHITE);
app.update(); app.update();
@ -206,7 +213,7 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
quote! { quote! {
#[macroquad::main(#window_title)] #[macroquad::main(#window_title)]
async fn main() { async fn main() {
// Parse command-line arguments for SVG export // Parse command-line arguments for SVG export FIRST (before any graphics init)
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let mut export_svg_path: Option<String> = None; let mut export_svg_path: Option<String> = None;
@ -219,22 +226,21 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
i += 1; i += 1;
} }
let mut turtle = turtle_lib::create_turtle_plan(); // Handle SVG export mode (execute instantly without rendering)
// Inline the user's code
#fn_block
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
// Handle SVG export if requested
if let Some(filename) = export_svg_path { if let Some(filename) = export_svg_path {
#[cfg(feature = "svg")] #[cfg(feature = "svg")]
{ {
let mut turtle = turtle_lib::create_turtle_plan();
#fn_block
// Create app and execute instantly
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
// Set instant speed to execute all commands immediately // Set instant speed to execute all commands immediately
app.set_all_turtles_speed(turtle_lib::AnimationSpeed::Instant(1000)); app.set_all_turtles_speed(turtle_lib::AnimationSpeed::Instant(1000));
// Execute all commands instantly // Execute all commands instantly (no rendering needed)
while !app.all_animations_complete() { while !app.all_animations_complete() {
app.update(); app.update();
} }
@ -259,7 +265,13 @@ pub fn turtle_main(args: TokenStream, input: TokenStream) -> TokenStream {
} }
} }
// Normal rendering loop // Normal rendering mode (with window)
let mut turtle = turtle_lib::create_turtle_plan();
#fn_block
let mut app = turtle_lib::TurtleApp::new()
.with_commands(turtle.build());
loop { loop {
macroquad::prelude::clear_background(macroquad::prelude::WHITE); macroquad::prelude::clear_background(macroquad::prelude::WHITE);
app.update(); app.update();

View File

@ -0,0 +1,36 @@
//! Test example for CLI SVG export feature
//!
//! Run this with: cargo run --package turtle-lib --example test_svg_export --features svg -- --export-svg test_output.svg
use turtle_lib::*;
#[turtle_main("SVG Export Test")]
fn draw_test(turtle: &mut TurtlePlan) {
turtle.set_pen_color(RED);
turtle.set_pen_width(3.0);
// Draw a square
for _ in 0..4 {
turtle.forward(100.0);
turtle.right(90.0);
}
// Draw a circle
turtle.set_pen_color(BLUE);
turtle.pen_up();
turtle.forward(150.0);
turtle.pen_down();
turtle.circle_left(50.0, 360.0, 36);
// Draw a filled triangle
turtle.set_fill_color(GREEN);
turtle.pen_up();
turtle.go_to(vec2(-50.0, 100.0));
turtle.pen_down();
turtle.begin_fill();
for _ in 0..3 {
turtle.forward(80.0);
turtle.right(120.0);
}
turtle.end_fill();
}