Browse Source

Refactor to use subcommands

Kevin Lee 6 months ago
parent
commit
0a1ed95d37
3 changed files with 170 additions and 130 deletions
  1. 3 3
      src/config/object.rs
  2. 13 1
      src/ezcad/objects/mod.rs
  3. 154 126
      src/main.rs

+ 3 - 3
src/config/object.rs

@@ -227,8 +227,8 @@ impl ObjectOperation {
                     // Build new hatch object (no hatch lines)
                     // Build new hatch object (no hatch lines)
                     Object::Hatch(Hatch {
                     Object::Hatch(Hatch {
                         core: ObjectCore {
                         core: ObjectCore {
-                            origin: object.core().origin,
-                            z: object.core().z,
+                            origin: object.core_mut().origin,
+                            z: object.core_mut().z,
                             ..ObjectCore::default(ObjectType::Hatch)
                             ..ObjectCore::default(ObjectType::Hatch)
                         },
                         },
                         outline: vec![object].into(),
                         outline: vec![object].into(),
@@ -285,7 +285,7 @@ impl ObjectOperation {
 
 
                         debug!(
                         debug!(
                             "Adding new object at {} with pen #{}",
                             "Adding new object at {} with pen #{}",
-                            object.core().origin,
+                            object.core_mut().origin,
                             pen
                             pen
                         );
                         );
                         new_obj.push(object);
                         new_obj.push(object);

+ 13 - 1
src/ezcad/objects/mod.rs

@@ -223,7 +223,7 @@ impl Object {
         }
         }
     }
     }
 
 
-    pub fn core(&mut self) -> &mut ObjectCore {
+    pub fn core_mut(&mut self) -> &mut ObjectCore {
         match self {
         match self {
             Object::Curve(x) => &mut x.core,
             Object::Curve(x) => &mut x.core,
             Object::Point(x) => &mut x.core,
             Object::Point(x) => &mut x.core,
@@ -234,6 +234,18 @@ impl Object {
             Object::Hatch(x) => &mut x.core,
             Object::Hatch(x) => &mut x.core,
         }
         }
     }
     }
+
+    pub fn core(&self) -> &ObjectCore {
+        match self {
+            Object::Curve(x) => &x.core,
+            Object::Point(x) => &x.core,
+            Object::Rectangle(x) => &x.core,
+            Object::Circle(x) => &x.core,
+            Object::Ellipse(x) => &x.core,
+            Object::Polygon(x) => &x.core,
+            Object::Hatch(x) => &x.core,
+        }
+    }
 }
 }
 
 
 #[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
 #[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]

+ 154 - 126
src/main.rs

@@ -6,11 +6,11 @@ use std::{
 };
 };
 
 
 use binrw::{BinRead, BinWrite, BinWriterExt};
 use binrw::{BinRead, BinWrite, BinWriterExt};
-use clap::Parser;
+use clap::{Args, Parser, Subcommand};
 use clap_verbosity_flag::{InfoLevel, Verbosity};
 use clap_verbosity_flag::{InfoLevel, Verbosity};
 use diff::Diff;
 use diff::Diff;
 use env_logger::Target;
 use env_logger::Target;
-use ezcad::file::EzCadHeader;
+use ezcad::{file::EzCadHeader, layer::Layer, objects::Object};
 use log::{info, trace, warn};
 use log::{info, trace, warn};
 
 
 use crate::config::{Config, Operations};
 use crate::config::{Config, Operations};
@@ -19,36 +19,58 @@ mod config;
 
 
 #[derive(Debug, Parser)]
 #[derive(Debug, Parser)]
 struct Cli {
 struct Cli {
-    /// Input file to parse
+    #[command(subcommand)]
+    command: SubCommands,
+
+    /// Input .mlp file to parse
     #[arg(short, long)]
     #[arg(short, long)]
     input: PathBuf,
     input: PathBuf,
 
 
-    /// File to diff input against
-    #[arg(short, long)]
-    diff: Option<PathBuf>,
+    #[command(flatten)]
+    verbose: Verbosity<InfoLevel>,
+}
 
 
-    /// Output file to write to
-    #[arg(short, long)]
-    output: Option<PathBuf>,
+#[derive(Debug, Subcommand)]
+enum SubCommands {
+    Diff(DiffCmd),
+    Query(QueryCmd),
+    Apply(ApplyConfig),
+}
 
 
-    /// Configuration file
+/// Diff two .mlp files and print differences between the two
+#[derive(Debug, Args)]
+struct DiffCmd {
+    /// File to diff input against
     #[arg(short, long)]
     #[arg(short, long)]
-    config: Option<PathBuf>,
+    diff_file: PathBuf,
+}
 
 
+/// Queries input .mlp file for pen or object info
+#[derive(Debug, Args)]
+struct QueryCmd {
     /// Print pen info
     /// Print pen info
     #[arg(short, long)]
     #[arg(short, long)]
     pen: Option<Vec<usize>>,
     pen: Option<Vec<usize>>,
 
 
-    // /// Layer of object to print info
-    // #[arg(short = 'l', long, requires = "object")]
-    // object_layer: Option<usize>,
+    /// Print object info
+    #[arg(short, long)]
+    object: Option<usize>,
 
 
-    // /// Print object info
-    // #[arg(short = 'b', long)]
-    // object: Option<usize>,
+    /// Object layer to query object on
+    #[arg(short = 'b', long)]
+    object_layer: Option<usize>,
+}
 
 
-    #[command(flatten)]
-    verbose: Verbosity<InfoLevel>,
+/// Applies configuration YAML to input .mlp file
+#[derive(Debug, Args)]
+struct ApplyConfig {
+    /// Configuration file
+    #[arg(short, long)]
+    config: PathBuf,
+
+    /// Output file to write to
+    #[arg(short, long)]
+    output: Option<PathBuf>,
 }
 }
 
 
 fn main() {
 fn main() {
@@ -89,121 +111,127 @@ fn main() {
         warn!("Re-encoded input file does not match original file!");
         warn!("Re-encoded input file does not match original file!");
     }
     }
 
 
-    // Print info on pens with non-default settings
-    for (index, pen) in file
-        .pens_offset
-        .data
-        .pens
-        .iter()
-        .filter(|x| *x.use_default == 0)
-        .enumerate()
-    {
-        trace!("Pen {}: {:#?}", index, pen);
-    }
-
-    // Print all objects
-    for (layer_index, layer) in file.layers_offset.iter().enumerate() {
-        for (object_index, object) in layer.objects.iter().enumerate() {
-            trace!(
-                "Layer {}, Object {}: {:#?}",
-                layer_index,
-                object_index,
-                object
+    match cli.command {
+        SubCommands::Diff(args) => {
+            info!(
+                "Processing diff file '{}'",
+                args.diff_file.to_string_lossy()
             );
             );
-        }
-    }
+            let mut diff: File = File::open(args.diff_file).expect("Failed to open diff file");
+            let diff_file: EzCadHeader =
+                EzCadHeader::read_le(&mut diff).expect("Failed to parse diff file as EZCAD format");
 
 
-    // Process pen query
-    cli.pen.map(|index| {
-        for pen in index {
+            // Diff pens
             info!(
             info!(
-                "Pen #{}: {}",
-                pen,
+                "{:#?}",
                 file.pens_offset
                 file.pens_offset
                     .data
                     .data
                     .pens
                     .pens
-                    .get(pen)
-                    .expect("Invalid pen index")
+                    .diff(&diff_file.pens_offset.data.pens)
+            );
+
+            // Diff objects
+            info!(
+                "{:#?}",
+                file.layers_offset
+                    .value
+                    .diff(&diff_file.layers_offset.value)
             );
             );
         }
         }
-    });
-
-    // Process object query
-    // cli.object.map(|obj_index| {
-    //     let layer_index: usize = cli.object_layer.unwrap_or(0);
-    //     let layer: &Layer = file
-    //         .layers_offset
-    //         .get(layer_index)
-    //         .expect("Invalid layer index");
-    //     let object: &Object = layer.objects.get(obj_index).expect("Invalid object index");
-    //     info!("Layer {}, Object {}: {:?}", layer_index, obj_index, object);
-    //     let pen_index: u32 = object.get_pen();
-    //     trace!(
-    //         "Pen #{}: {}",
-    //         pen_index,
-    //         file.pens_offset
-    //             .data
-    //             .pens
-    //             .get(pen_index as usize)
-    //             .expect("Invalid pen index in object")
-    //     );
-    //     // TODO: object info
-    // });
-
-    // Process diff
-    cli.diff.map(|diff| {
-        info!("Processing diff file '{}'", diff.to_string_lossy());
-        let mut diff: File = File::open(diff).expect("Failed to open diff file");
-        let diff_file: EzCadHeader =
-            EzCadHeader::read_le(&mut diff).expect("Failed to parse diff file as EZCAD format");
-
-        // Diff pens
-        info!(
-            "{:#?}",
-            file.pens_offset
+        SubCommands::Query(args) => {
+            // Print info on pens with non-default settings
+            for (index, pen) in file
+                .pens_offset
                 .data
                 .data
                 .pens
                 .pens
-                .diff(&diff_file.pens_offset.data.pens)
-        );
-
-        // Diff objects
-        info!(
-            "{:#?}",
-            file.layers_offset
-                .value
-                .diff(&diff_file.layers_offset.value)
-        );
-    });
-
-    // Process config
-    cli.config.map(|config| {
-        info!("Processing config file '{}'", config.to_string_lossy());
-        let config: String = std::fs::read_to_string(config).expect("Failed to open config file");
-        let config: Config = serde_yaml::from_str(&config).expect("Failed to parse config file");
-
-        // Patch pen settings
-        let time: Instant = Instant::now();
-        config
-            .ops
-            .apply(&mut file.pens_offset.data.pens, &mut file.layers_offset);
-        trace!("Config processing time: {:?}", time.elapsed());
-    });
-
-    // Process output
-    cli.output.map(|output| {
-        info!("Writing output file '{}'", output.to_string_lossy());
-        // Serialize to memory buffer for perf
-        let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
-        let time: Instant = Instant::now();
-        buffer
-            .write_le(&file)
-            .expect("Failed to serialize contents as EZCAD format");
-        trace!("Output file encode time: {:?}", time.elapsed());
-
-        // Write buffer to output file
-        let mut output: File = File::create(output).expect("Failed to open output file");
-        output
-            .write_all(buffer.into_inner().as_slice())
-            .expect("Failed to write to output file");
-    });
+                .iter()
+                .filter(|x| *x.use_default == 0)
+                .enumerate()
+            {
+                trace!("Pen {}: {:#?}", index, pen);
+            }
+
+            // Print all objects
+            for (layer_index, layer) in file.layers_offset.iter().enumerate() {
+                for (object_index, object) in layer.objects.iter().enumerate() {
+                    trace!(
+                        "Layer {}, Object {}: {:#?}",
+                        layer_index,
+                        object_index,
+                        object
+                    );
+                }
+            }
+
+            // Process pen query
+            args.pen.map(|pens| {
+                for pen in pens {
+                    info!(
+                        "Pen #{}: {}",
+                        pen,
+                        file.pens_offset
+                            .data
+                            .pens
+                            .get(pen)
+                            .expect("Invalid pen index")
+                    );
+                }
+            });
+
+            // Process object query
+            args.object.map(|obj_index| {
+                let layer_index: usize = args.object_layer.unwrap_or(0);
+                let layer: &Layer = file
+                    .layers_offset
+                    .get(layer_index)
+                    .expect("Invalid layer index");
+                let object: &Object = layer.objects.get(obj_index).expect("Invalid object index");
+                info!("Layer {}, Object {}: {:?}", layer_index, obj_index, object);
+                let pen_index: u32 = *object.core().pen;
+                trace!(
+                    "Pen #{}: {}",
+                    pen_index,
+                    file.pens_offset
+                        .data
+                        .pens
+                        .get(pen_index as usize)
+                        .expect("Invalid pen index in object")
+                );
+                // TODO: object info
+            });
+        }
+        SubCommands::Apply(args) => {
+            // Process config
+            info!("Processing config file '{}'", args.config.to_string_lossy());
+            let config: String =
+                std::fs::read_to_string(args.config).expect("Failed to open config file");
+            let config: Config =
+                serde_yaml::from_str(&config).expect("Failed to parse config file");
+
+            // Patch pen settings
+            let time: Instant = Instant::now();
+            config
+                .ops
+                .apply(&mut file.pens_offset.data.pens, &mut file.layers_offset);
+            trace!("Config processing time: {:?}", time.elapsed());
+
+            // Process output
+            args.output.map(|output| {
+                info!("Writing output file '{}'", output.to_string_lossy());
+                // Serialize to memory buffer for perf
+                let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
+                let time: Instant = Instant::now();
+                buffer
+                    .write_le(&file)
+                    .expect("Failed to serialize contents as EZCAD format");
+                trace!("Output file encode time: {:?}", time.elapsed());
+
+                // Write buffer to output file
+                let mut output: File = File::create(output).expect("Failed to open output file");
+                output
+                    .write_all(buffer.into_inner().as_slice())
+                    .expect("Failed to write to output file");
+            });
+        }
+    }
 }
 }