From 2d9fa036b24bdb71da7afd1cd7532f037aee60f9 Mon Sep 17 00:00:00 2001 From: Sameer Puri Date: Thu, 1 Jun 2023 14:26:28 -0700 Subject: [PATCH] options for line numbers and checksums, closes #35 --- Cargo.lock | 49 ++++++++++----------- cli/src/main.rs | 40 ++++++++++++++++- lib/Cargo.toml | 4 +- lib/src/lib.rs | 53 +++++++++++++++++++++++ lib/src/postprocess.rs | 9 +++- web/src/forms/inputs.rs | 4 +- web/src/forms/mod.rs | 96 ++++++++++++++++++++++++++++++----------- web/src/main.rs | 26 +++++------ web/src/state.rs | 9 +++- 9 files changed, 217 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3caa4f5..baf2a03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,7 +59,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -407,7 +407,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -442,9 +442,9 @@ dependencies = [ [[package]] name = "g-code" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af84627294d66ff823b6947819ae8878db6b5d78d1bf9e86b1073026b6f3db83" +checksum = "426e8db123028351d46f0befecb1fe15e326ab53cd9449c1296083981859519c" dependencies = [ "codespan", "codespan-reporting", @@ -757,12 +757,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "lyon_geom" @@ -803,9 +800,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" [[package]] name = "paste" @@ -863,7 +860,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -1145,7 +1142,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -1245,7 +1242,7 @@ dependencies = [ [[package]] name = "svg2gcode" -version = "0.1.1" +version = "0.1.2" dependencies = [ "cairo-rs", "euclid", @@ -1325,9 +1322,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45b6ddbb36c5b969c182aec3c4a0bce7df3fbad4b77114706a49aacc80567388" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -1394,7 +1391,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -1414,9 +1411,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "pin-project-lite", @@ -1497,7 +1494,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", ] [[package]] @@ -1594,7 +1591,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", "wasm-bindgen-shared", ] @@ -1628,7 +1625,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1823,9 +1820,9 @@ dependencies = [ [[package]] name = "yewdux" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653ba356bc60d1804c28ec6cc8ddac2741c686bde2a65074d07faba735914464" +checksum = "3c528544a814a0beb30059c8340eb78c88160141db788112b51a5a08098cef2d" dependencies = [ "anymap", "async-trait", @@ -1842,9 +1839,9 @@ dependencies = [ [[package]] name = "yewdux-macros" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bcd923aceaa85cb4affad8657cc36e3d6b6932740e711574182f7817492739" +checksum = "cc318072e34a9083d651ecd126153e9f1c39ae705794ef953a30b561b5eaab6d" dependencies = [ "darling", "proc-macro-error", diff --git a/cli/src/main.rs b/cli/src/main.rs index c2b7877..6196222 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -67,6 +67,17 @@ struct Opt { /// Please check if your machine supports G2/G3 commands before enabling this. #[structopt(long)] circular_interpolation: Option, + + #[structopt(long)] + /// Include line numbers at the beginning of each line + /// + /// Useful for debugging/streaming g-code + line_numbers: Option, + #[structopt(long)] + /// Include checksums at the end of each line + /// + /// Useful for streaming g-code + checksums: Option, } fn main() -> io::Result<()> { @@ -128,6 +139,15 @@ fn main() -> io::Result<()> { } } } + + if let Some(line_numbers) = opt.line_numbers { + settings.postprocess.line_numbers = line_numbers; + } + + if let Some(checksums) = opt.checksums { + settings.postprocess.checksums = checksums; + } + settings }; @@ -253,8 +273,24 @@ fn main() -> io::Result<()> { let program = svg2program(&document, &settings.conversion, options, machine); if let Some(out_path) = opt.out { - format_gcode_io(&program, FormatOptions::default(), File::create(out_path)?) + format_gcode_io( + &program, + FormatOptions { + line_numbers: settings.postprocess.line_numbers, + checksums: settings.postprocess.checksums, + ..Default::default() + }, + File::create(out_path)?, + ) } else { - format_gcode_io(&program, FormatOptions::default(), std::io::stdout()) + format_gcode_io( + &program, + FormatOptions { + line_numbers: settings.postprocess.line_numbers, + checksums: settings.postprocess.checksums, + ..Default::default() + }, + std::io::stdout(), + ) } } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 7f61947..6ba0645 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "svg2gcode" -version = "0.1.1" +version = "0.1.2" authors = ["Sameer Puri "] edition = "2021" description = "Convert paths in SVG files to GCode for a pen plotter, laser engraver, or other machine." @@ -8,7 +8,7 @@ repository = "https://github.com/sameer/svg2gcode" license = "MIT" [dependencies] -g-code = { version = "0.3.4", features = ["serde"] } +g-code = { version = "0.3.5", features = ["serde"] } lyon_geom = "1.0.4" euclid = "0.22" log = "0.4" diff --git a/lib/src/lib.rs b/lib/src/lib.rs index ba3e5b9..3ac253f 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -162,4 +162,57 @@ mod test { "#; serde_json::from_str::(json).unwrap(); } + + #[test] + #[cfg(feature = "serde")] + fn deserialize_v2_config_succeeds() { + let json = r#" + { + "conversion": { + "tolerance": 0.002, + "feedrate": 300.0, + "dpi": 96.0 + }, + "machine": { + "supported_functionality": { + "circular_interpolation": true + }, + "tool_on_sequence": null, + "tool_off_sequence": null, + "begin_sequence": null, + "end_sequence": null + }, + "postprocess": { } + } + "#; + serde_json::from_str::(json).unwrap(); + } + + #[test] + #[cfg(feature = "serde")] + fn deserialize_v3_config_succeeds() { + let json = r#" + { + "conversion": { + "tolerance": 0.002, + "feedrate": 300.0, + "dpi": 96.0 + }, + "machine": { + "supported_functionality": { + "circular_interpolation": true + }, + "tool_on_sequence": null, + "tool_off_sequence": null, + "begin_sequence": null, + "end_sequence": null + }, + "postprocess": { + "checksums": false, + "line_numbers": false + } + } + "#; + serde_json::from_str::(json).unwrap(); + } } diff --git a/lib/src/postprocess.rs b/lib/src/postprocess.rs index d3ee350..7c3b3c0 100644 --- a/lib/src/postprocess.rs +++ b/lib/src/postprocess.rs @@ -3,4 +3,11 @@ use serde::{Deserialize, Serialize}; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[derive(Debug, Default, Clone, PartialEq)] -pub struct PostprocessConfig {} +pub struct PostprocessConfig { + /// Convenience field for [g_code::emit::FormatOptions] field + #[cfg_attr(feature = "serde", serde(default))] + pub checksums: bool, + /// Convenience field for [g_code::emit::FormatOptions] field + #[cfg_attr(feature = "serde", serde(default))] + pub line_numbers: bool, +} diff --git a/web/src/forms/inputs.rs b/web/src/forms/inputs.rs index 6ae6cf2..02007e2 100644 --- a/web/src/forms/inputs.rs +++ b/web/src/forms/inputs.rs @@ -69,13 +69,13 @@ form_input! { } OriginX { "Origin X", - "X-axis coordinate for the bottom left corner of the machine", + "X-axis coordinate for the lower left corner of the machine", origin => 0, settings.conversion.origin => 0, } OriginY { "Origin Y", - "Y-axis coordinate for the bottom left corner of the machine", + "Y-axis coordinate for the lower left corner of the machine", origin => 1, settings.conversion.origin => 1, } diff --git a/web/src/forms/mod.rs b/web/src/forms/mod.rs index 124ab02..fd9dc4c 100644 --- a/web/src/forms/mod.rs +++ b/web/src/forms/mod.rs @@ -65,13 +65,21 @@ pub fn settings_form() -> Html { // but historically hasn't been the case, on change is safer. let on_circular_interpolation_change = form_dispatch.reduce_mut_callback_with(|form, event: Event| { - let checkbox = event.target_unchecked_into::(); - form.circular_interpolation = checkbox.checked(); + form.circular_interpolation = + event.target_unchecked_into::().checked(); }); - let circular_interpolation_checked = form_state.circular_interpolation; + + let on_checksums_change = form_dispatch.reduce_mut_callback_with(|form, event: Event| { + form.checksums = event.target_unchecked_into::().checked(); + }); + + let on_line_numbers_change = form_dispatch.reduce_mut_callback_with(|form, event: Event| { + form.line_numbers = event.target_unchecked_into::().checked(); + }); let save_onclick = { let close_ref = close_ref.clone(); + let form_state = form_state.clone(); app_dispatch.reduce_mut_callback(move |app| { if !disabled { app.settings = form_state.as_ref().try_into().unwrap(); @@ -104,25 +112,65 @@ pub fn settings_form() -> Html { ) } body={html!( - <> - - - - - - - - - - - - - +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+ + + +
+
)} footer={ html!( @@ -221,9 +269,9 @@ pub fn import_export_modal() -> Html { let close_ref = close_ref.clone(); app_dispatch.reduce_mut_callback(move |app| { if let Some(Ok(ref settings)) = *import_state { - app.settings = settings.clone(); + app.settings = settings.clone(); // App only hydrates the form on start now, so need to do it again here - form_dispatch.reduce_mut(|form| *form = (&app.settings).into()); + form_dispatch.reduce_mut(|form| *form = (&app.settings).into()); import_state.set(None); // TODO: another way to close the modal? if let Some(element) = close_ref.cast::() { diff --git a/web/src/main.rs b/web/src/main.rs index 5d9cb76..c9cc452 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -21,19 +21,6 @@ use ui::*; use util::*; use yewdux::prelude::{use_store, Dispatch}; -// struct App { -// app_store: Rc, -// form_state: Rc, -// generating: bool, -// } - -// enum AppMsg { -// AppState(Rc), -// FormState(Rc), -// Generate, -// Done, -// } - #[function_component] fn App(_props: &()) -> Html { let generating = use_state_eq(|| false); @@ -104,8 +91,17 @@ fn App(_props: &()) -> Html { svg2program(&document, &app_store.settings.conversion, options, machine); let gcode = { - let mut acc = String::new(); - format_gcode_fmt(&program, FormatOptions::default(), &mut acc).unwrap(); + let mut acc: String = String::new(); + format_gcode_fmt( + &program, + FormatOptions { + checksums: app_store.settings.postprocess.checksums, + line_numbers: app_store.settings.postprocess.line_numbers, + ..Default::default() + }, + &mut acc, + ) + .unwrap(); acc }; diff --git a/web/src/state.rs b/web/src/state.rs index 48d61b1..3a6775c 100644 --- a/web/src/state.rs +++ b/web/src/state.rs @@ -19,6 +19,8 @@ pub struct FormState { pub tool_off_sequence: Option>, pub begin_sequence: Option>, pub end_sequence: Option>, + pub checksums: bool, + pub line_numbers: bool, } impl Default for FormState { @@ -75,7 +77,10 @@ impl<'a> TryInto for &'a FormState { .transpose() .map_err(FormStateConversionError::GCode)?, }, - postprocess: PostprocessConfig {}, + postprocess: PostprocessConfig { + checksums: self.checksums, + line_numbers: self.line_numbers, + }, }) } } @@ -98,6 +103,8 @@ impl From<&Settings> for FormState { tool_off_sequence: settings.machine.tool_off_sequence.clone().map(Ok), begin_sequence: settings.machine.begin_sequence.clone().map(Ok), end_sequence: settings.machine.end_sequence.clone().map(Ok), + checksums: settings.postprocess.checksums, + line_numbers: settings.postprocess.line_numbers, } } }