Commit Graph
12 Commits
Author SHA1 Message Date
dietrich b19919f8b7 CLI --export-svg Error Handling with pico-args
We resolved two issues when running turtle programs with `--export-svg`:
1. **Missing filename**: Previously, running `--export-svg` without a
   filename caused the CLI parser to ignore the flag and open the GUI
   window. Now, it emits `Error: --export-svg: option requires an
   argument` and terminates with exit code 1.
2. **Missing `svg` feature**: Previously, running `--export-svg` without
   the `svg` feature enabled ignored the flag if no filename was passed
   and opened the window. Now, any invocation of `--export-svg` without
   `--features svg` emits `Error: SVG export feature is not enabled.
   Please rebuild with --features svg` and terminates with exit code 1.

---

- Added [`pico-args = { version = "0.5", features = ["eq-separator"]
  }`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/Cargo.toml)
  under `[dependencies]`.
- In
  [`turtle-lib/src/export.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/export.rs):
  - Added `MissingFeature(String)` to `ExportError` for clean error
    display.
  - Implemented `parse_svg_export_from_args(args: &mut
    pico_args::Arguments) -> Result<Option<String>, pico_args::Error>`
    to parse `--export-svg <file>` and `--export-svg=<file>`, treating
    empty or flag arguments as missing values (`OptionWithoutAValue`).
  - Updated `parse_svg_export_arg() -> Option<String>` for backward
    compatibility.
  - In `handle_svg_export`:
    - Under `#[cfg(not(feature = "svg"))]`: detects any presence of
      `--export-svg`, outputs `Error: SVG export feature is not enabled.
      Please rebuild with --features svg`, and exits with code 1.
    - Under `#[cfg(feature = "svg")]`: handles missing arguments with
      `Error: --export-svg: option requires an argument` (exit 1), valid
      exports (exit 0), and leaves unknown arguments untouched so
      Macroquad or user flags continue to work.
  - Added unit tests covering all flag parsing variants and error
    displays.

- In
  [`turtle-lib-macros/src/lib.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib-macros/src/lib.rs):
  - Simplified the macro expansion in `turtle_main` to delegate directly
    to `turtle_lib::export::handle_svg_export(&mut build_commands);`.
  - Updated documentation comments to match.

---

```bash
cargo test --package turtle-lib
cargo test --package turtle-lib --features svg
cargo test --package turtle-lib-macros
cargo clippy --package turtle-lib -- -Wclippy::pedantic
-Aclippy::cast_precision_loss -Aclippy::cast_sign_loss
-Aclippy::cast_possible_truncation
cargo clippy --package turtle-lib --features svg -- -Wclippy::pedantic
-Aclippy::cast_precision_loss -Aclippy::cast_sign_loss
-Aclippy::cast_possible_truncation
cargo clippy --package turtle-lib-macros -- -Wclippy::pedantic
```
- **Unit tests**: All 29 unit tests in `turtle-lib` and 18 unit tests in
  `turtle-lib-macros` passed.
- **Doctests**: All 34 doctests passed.
- **Clippy**: Passed with zero warnings across all crates and feature
  configurations.

| Scenario | Command | Result | Exit Code | Window Opened? |
|---|---|---|---|---|
| Missing feature, missing filename | `cargo run --example hello_turtle
-- --export-svg` | `Error: SVG export feature is not enabled. Please
rebuild with --features svg` | 1 | No |
| Missing feature, with filename | `cargo run --example hello_turtle --
--export-svg test.svg` | `Error: SVG export feature is not enabled.
Please rebuild with --features svg` | 1 | No |
| Feature enabled, missing filename | `cargo run --example hello_turtle
--features svg -- --export-svg` | `Error: --export-svg: option requires
an argument` | 1 | No |
| Feature enabled, with filename | `cargo run --example hello_turtle
--features svg -- --export-svg /tmp/pico_test.svg` | `SVG exported
successfully to: /tmp/pico_test.svg` | 0 | No |
| Feature enabled, equals syntax | `cargo run --example hello_turtle
--features svg -- --export-svg=/tmp/pico_test_eq.svg` | `SVG exported
successfully to: /tmp/pico_test_eq.svg` | 0 | No |
| Feature enabled, extra flags | `cargo run --example hello_turtle
--features svg -- --export-svg /tmp/pico_test_extra.svg --custom-flag` |
`SVG exported successfully to: /tmp/pico_test_extra.svg` | 0 | No |
| Normal run (no flag) | `cargo run --example hello_turtle` |
Interactive window opens normally | 0 | Yes |
2026-09-20 12:36:15 +02:00
dietrich f117361950 Fix Timing Clocks Divergence
Fixed the timing clock divergence between
[tweening.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs)
and
[drawing.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs)
by delegating animation progress evaluation exclusively to
`TweenController`.

`current_time()` in `tweening.rs` was using a monotonic `Instant` epoch
(to support headless execution and unit tests without panicking on
missing Macroquad context), while `drawing.rs` was measuring progress
via `macroquad::time::get_time() - tween.start_time`. Because these two
clocks operate on completely different epochs, subtracting them caused
negative elapsed times, premature clamping, jitter, or animation lockup.

In
[`turtle-lib/src/tweening.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs):
- Added `pub(crate) progress: f32` to
  [`CommandTween`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs#L55-L68)
  to track the current evaluated, eased progress in `[0.0, 1.0]`.
- Made `start_time: f64` and `duration: f64` private to `tweening.rs` so
  outside modules cannot accidentally perform desynchronized clock
  arithmetic.
- Initialized `progress: 0.0` when constructing a new `CommandTween`.
- In `TweenController::update`, evaluated and clamped `tween.progress =
  tween.heading_tweener.move_to(elapsed).clamp(0.0, 1.0)`.

In
[`turtle-lib/src/drawing.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs):
- Removed `use tween::CubicInOut;` and duplicate easing calculations.
- Replaced `get_time() - tween.start_time` and `CubicInOut.tween(...)`
  in in-flight fill preview with `tween.progress`.
- Replaced `get_time() - tween.start_time` and `CubicInOut.tween(...)`
  in `draw_tween_arc` with `tween.progress`.
- Ensured `drawing.rs` has zero clock queries and strictly renders the
  state provided by `TweenController`.

In
[`turtle-lib/src/tweening.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs#L540-L579):
- Updated `test_animated_mode_pops_to_current_tween` to assert that
  `progress` initializes to `0.0`.
- Added `test_animated_mode_progress_advances_and_clamps` to verify that
  `progress` advances monotonically across frames and stays within
  `[0.0, 1.0]`.

---

```bash
cargo test --package turtle-lib --features svg
```
Output:
```text
running 17 tests
test circle_geometry::tests::test_circle_left_geometry ... ok
test circle_geometry::tests::test_circle_right_geometry ... ok
test command_behavior::tests::test_goto_duration_cartesian_inversion ...
ok
test
command_behavior::tests::test_set_heading_degrees_and_instant_duration
... ok
test execution::tests::test_forward_left_forward ... ok
test general::angle::tests::degrees_to_radians_roundtrip ... ok
test general::angle::tests::from_f64 ... ok
test general::angle::tests::from_integer ... ok
test general::angle::tests::negation ... ok
test general::fontsize::tests::font_size_conversions ... ok
test general::length::tests::test_length_conversions_and_negation ... ok
test general::tests::animation_speed_conversions ... ok
test tweening::tests::test_animated_mode_pops_to_current_tween ... ok
test tweening::tests::test_instant_mode_drains_queue ... ok
test
tweening::tests::test_instant_mode_respects_batch_limit_and_retains_pending
... ok
test tweening::tests::test_streaming_append_commands_does_not_accumulate
... ok
test tweening::tests::test_animated_mode_progress_advances_and_clamps
... ok

test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered
out; finished in 0.02s

Doc-tests turtle_lib: 34 passed; 0 failed; 1 ignored; 0 measured; 0
filtered out; finished in 0.26s
```

```bash
cargo clippy --package turtle-lib --features svg -- -Wclippy::pedantic \
-Aclippy::cast_precision_loss -Aclippy::cast_sign_loss
-Aclippy::cast_possible_truncation
```
Output:
```text
Finished `dev` profile [optimized + debuginfo] target(s) in 0.82s
```
**0 warnings.**

```bash
cargo run --example yinyang --features svg -- --export-svg
/tmp/yinyang_test.svg
```
Output:
```text
SVG exported successfully to: /tmp/yinyang_test.svg
```

```bash
cargo build --package turtle-lib --examples
```
Output:
```text
Finished `dev` profile [optimized + debuginfo] target(s) in 6.74s
```
**All 30 examples compiled cleanly with 0 errors and 0 warnings.**
2026-09-19 10:52:00 +02:00
dietrich 5e0e0e5be3 update the dependencies 2026-05-22 15:13:22 +02:00
dietrich 6e6aa8b27e initial svg support 2025-10-23 09:40:08 +02:00
dietrich b31ac29deb add clock and bezier example 2025-10-18 22:19:02 +02:00
dietrich 28527e6113 improve hangman 2025-10-18 21:35:45 +02:00
dietrich 3f21afadb2 add threading 2025-10-17 19:16:19 +02:00
dietrich 3509060390 add multi turtle support 2025-10-17 08:59:29 +02:00
dietrich 08a1802bd2 remove the bevy based turtle and rename turtle-lib-macroquad to turtle-lib 2025-10-12 20:31:05 +02:00
dietrich fe2beb01ed remove the bevy turtle 2025-10-12 19:39:09 +02:00
dietrich 8a56176ceb first port to modern bevy 2025-10-01 17:10:27 +02:00
dietrich f1591bc9f1 Moved files 2023-01-25 12:03:07 +01:00