diff --git a/stackline-cli/src/main.rs b/stackline-cli/src/main.rs index 7f1b1b7..e68d580 100644 --- a/stackline-cli/src/main.rs +++ b/stackline-cli/src/main.rs @@ -7,19 +7,30 @@ use std::path::{Path, PathBuf}; use std::time::Duration; use std::io::Write; -fn main() { - let args = Args::parse(); - // let mut world = World::new(); - // let mut pane = Pane::empty(4, 4).unwrap(); - // pane.set_tile((0, 0), FullTile::from(Wire::new(Orientation::Any))); - // world.set_pane(String::from("main"), pane); - // let raw = serde_json::to_string(&world).unwrap(); - // std::fs::write(&args.file, &raw).unwrap(); +#[derive(Parser, Debug)] +#[clap(author, version, about)] +struct Args { + #[clap(short, long, value_parser)] + file: Option, +} - let raw = std::fs::read_to_string(&args.file).expect(&format!("Couldn't open {}!", args.file.display())); +fn main() { + let args = Args::parse(); - let mut world: World = serde_json::from_str(&raw).unwrap(); + let mut world: World = if let Some(path) = &args.file { + match std::fs::read_to_string(path) { + Ok(raw) => { + serde_json::from_str(&raw).expect("Couldn't parse JSON") + } + Err(err) => { + eprintln!("Couldn't open {}: {}", path.display(), err); + return + } + } + } else { + World::new() + }; loop { let mut line = String::new(); @@ -43,6 +54,20 @@ fn main() { Some("print") => { print!("{}", world); } + Some("panes") => { + panes(&world); + } + + Some("pane") => { + if let (Some(name), Some(x), Some(y), Some(width), Some(height)) = (tokens.next(), tokens.next(), tokens.next(), tokens.next(), tokens.next()) { + if let (Ok(x), Ok(y), Ok(width), Ok(height)) = (x.parse(), y.parse(), width.parse(), height.parse()) { + pane(&mut world, name, x, y, width, height); + } + } else { + eprintln!("Expected five arguments"); + } + } + Some("get") => { if let (Some(x), Some(y)) = (tokens.next(), tokens.next()) { if let (Ok(x), Ok(y)) = (x.parse(), y.parse()) { @@ -52,7 +77,6 @@ fn main() { eprintln!("Expected two arguments"); } } - Some("set") => { if let (Some(x), Some(y), Some(name)) = (tokens.next(), tokens.next(), tokens.next()) { if let (Ok(x), Ok(y)) = (x.parse(), y.parse()) { @@ -139,15 +163,39 @@ fn main() { Some("load") => { if let Some(path) = tokens.next() { load(&mut world, path); + } else if let Some(path) = &args.file { + load(&mut world, path); } else { - load(&mut world, &args.file); + eprintln!("No file given with the -f option!"); } } Some("save") => { if let Some(path) = tokens.next() { save(&world, path); + } else if let Some(path) = &args.file { + save(&world, path); + } else { + eprintln!("No file given with the -f option!"); + } + } + + Some("copy") => { + if let (Some(x), Some(y), Some(x2), Some(y2)) = (tokens.next(), tokens.next(), tokens.next(), tokens.next()) { + if let (Ok(x), Ok(y), Ok(x2), Ok(y2)) = (x.parse(), y.parse(), x2.parse(), y2.parse()) { + copy(&mut world, x, y, x2, y2); + } + } else { + eprintln!("Expected four arguments"); + } + } + Some("move") => { + if let (Some(x), Some(y), Some(x2), Some(y2)) = (tokens.next(), tokens.next(), tokens.next(), tokens.next()) { + if let (Ok(x), Ok(y), Ok(x2), Ok(y2)) = (x.parse(), y.parse(), x2.parse(), y2.parse()) { + copy(&mut world, x, y, x2, y2); + remove(&mut world, x, y); + } } else { - save(&world, &args.file); + eprintln!("Expected four arguments"); } } @@ -181,13 +229,6 @@ fn main() { } } -#[derive(Parser, Debug)] -#[clap(author, version, about)] -struct Args { - #[clap(short, long, value_parser)] - file: PathBuf, -} - fn run(world: &mut World, steps: usize) -> std::io::Result<()> { let mut stdout = std::io::stdout(); let mut first = true; @@ -503,3 +544,48 @@ fn load(world: &mut World, path: impl AsRef) { } } } + +fn copy(world: &mut World, x: i32, y: i32, x2: i32, y2: i32) { + let mut from: FullTile = match world.get((x, y)) { + Some(tile) => { + (*tile).clone() + } + None => { + eprintln!("No tile at {}:{}!", x, y); + return + } + }; + + // TODO: register signal in Pane::signals + match world.get_mut_with_pos((x2, y2)) { + Some((tile, x2, y2)) => { + if let Some(mut signal) = from.take_signal() { + signal.set_position((x2, y2)); + from.set_signal(Some(signal)); + } + *tile = from; + } + None => { + eprintln!("No tile at {}:{}!", x2, y2); + } + } +} + +fn pane(world: &mut World, name: &str, x: i32, y: i32, width: usize, height: usize) { + let mut pane = match Pane::empty(width, height) { + Some(pane) => pane, + None => { + eprintln!("Invalid pane dimensions!"); + return + } + }; + + pane.set_position((x, y)); + world.set_pane(name.to_string(), pane); +} + +fn panes(world: &World) { + for (name, pane) in world.panes() { + println!("- {}: {}x{}, at {}:{}", name, pane.width(), pane.height(), pane.position().0, pane.position().1); + } +} diff --git a/stackline/src/signal.rs b/stackline/src/signal.rs index 1f7cb2e..2ab7096 100644 --- a/stackline/src/signal.rs +++ b/stackline/src/signal.rs @@ -119,7 +119,7 @@ impl Signal { self.position } - pub(crate) fn set_position(&mut self, position: (usize, usize)) { + pub fn set_position(&mut self, position: (usize, usize)) { self.position = position; } diff --git a/stackline/src/world.rs b/stackline/src/world.rs index 2e980bc..fc3829a 100644 --- a/stackline/src/world.rs +++ b/stackline/src/world.rs @@ -133,6 +133,10 @@ impl World { ) }) } + + pub fn panes(&self) -> &HashMap { + &self.panes + } } impl std::fmt::Display for World {