| 
					
				 | 
			
			
				@@ -1,17 +1,19 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use std::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fs::File, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     io::{Cursor, Read, Write}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ops::RangeInclusive, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     path::PathBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     time::Instant, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use binrw::{BinRead, BinWrite, BinWriterExt}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use clap::{Args, Parser, Subcommand}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use clap::{error::ErrorKind, Args, Error, Parser, Subcommand}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use clap_verbosity_flag::{InfoLevel, Verbosity}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use diff::Diff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use env_logger::Target; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use ezcad::{file::EzCadHeader, layer::Layer, objects::Object}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use log::{info, trace, warn}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use regex::Regex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use crate::config::{Config, Operations}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -45,14 +47,52 @@ struct DiffCmd { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     diff_file: PathBuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn parse_range(arg: &str) -> Result<RangeInclusive<usize>, Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let re: Regex = Regex::new(r"(\d+)?(\.{2})?(=)?(\d+)?").unwrap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const PEN_MAX: usize = 255; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    match re.captures(arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Some(found) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let range: bool = found.get(2).is_some(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let inclusive: bool = found.get(3).is_some(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let d1: Option<usize> = found 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .get(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .map(|x| usize::from_str_radix(x.as_str(), 10).unwrap()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let d2: Option<usize> = found 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .get(4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .map(|x| usize::from_str_radix(x.as_str(), 10).unwrap()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let ret = |d1: usize, d2: usize, inclusive: bool| -> RangeInclusive<usize> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                match inclusive { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    true => d1..=d2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    false => d1..=(d2 - 1), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            match (d1, d2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (None, None) if range => Ok(0..=PEN_MAX), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (None, None) => Err(Error::new(ErrorKind::InvalidValue)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (Some(d1), None) if !range => Ok(d1..=d1), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (Some(d1), None) => Ok(ret(d1, PEN_MAX, true)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (None, Some(d2)) if !range => Ok(d2..=d2), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (None, Some(d2)) => Ok(ret(0, d2, inclusive)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (Some(d1), Some(d2)) if d1 > d2 => Err(Error::new(ErrorKind::InvalidValue)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (Some(d1), Some(d2)) => Ok(ret(d1, d2, inclusive)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        _ => Err(Error::new(ErrorKind::InvalidValue)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /// Queries input .mlp file for pen or object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Debug, Args)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct QueryCmd { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Print pen info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Print info for pens 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pen: Option<Vec<usize>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(value_parser = parse_range)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pen: Option<RangeInclusive<usize>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Print object info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Print info for objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     object: Option<usize>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -164,8 +204,8 @@ fn main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // Process pen query 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            args.pen.map(|pens| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for pen in pens { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            args.pen.map(|pen_range| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for pen in pen_range { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     info!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         "Pen #{}: {}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         pen, 
			 |