diff --git a/src/box_.rs b/src/box_.rs new file mode 100644 index 0000000..d57cd58 --- /dev/null +++ b/src/box_.rs @@ -0,0 +1,93 @@ +use kakplugin::{ + get_selections_desc, set_selections_desc, AnchorPosition, KakError, SelectionDesc, +}; +use std::cmp::{max, min}; +#[derive(clap::StructOpt, Debug)] +pub struct Options { + // /// Bounding box mode, which selects the largest box to contain everything + // #[clap(short, long, help = "Select the bonding box of all selections")] + // bounding_box: bool, + // /// Allow selecting trailing newlines + // #[clap(short, long, help = "Allow selecting trailing newlines")] + // preserve_newlines: bool, +} + +pub fn box_(options: &Options) -> Result { + // TODO: Research if having multiple bounding boxes makes sense + // let ret_selection_descs = if options.bounding_box { + // // Get the bounding box and select it + // bounding_box(options)? + // } else { + // // Get a box per selection + // todo!("Implement per_selection(options: &Options);"); + // }; + + let ret_selection_descs = bounding_box(options)?; + + set_selections_desc(ret_selection_descs.iter())?; + + Ok(format!("Box {} selections", ret_selection_descs.len())) +} + +fn bounding_box(_options: &Options) -> Result, KakError> { + let selection_descs: Vec = get_selections_desc()? + .iter() + // TODO: Do they need to be sorted? + .map(|sd| sd.sort()) + .collect(); + + let (leftmost_col, rightmost_col) = selection_descs + .iter() + // Extract the columns so they can be reduced + // Make the left one be the smaller one in case the first one is max or min (reduce function would not be called) + .map(|sd| { + ( + min(sd.left.col, sd.right.col), + max(sd.left.col, sd.right.col), + ) + }) + // Get the smallest column or row + .reduce(|(leftmost_col, rightmost_col), (left, right)| { + ( + min(leftmost_col, min(left, right)), + max(rightmost_col, min(left, right)), + ) + }) + .ok_or_else(|| KakError::Custom(String::from("Selection is empty")))?; + + // Now, split on newline + // TODO: Should I use ? + // kakplugin::cmd(&format!("exec 'S\\n'"))?; + kakplugin::cmd(&format!("exec ''"))?; + // TODO: Here is where I might want selections to check if they end in newline + + let mut ret_selection_descs: Vec = vec![]; + + let split_selection_descs: Vec = + get_selections_desc()?.iter().map(|sd| sd.sort()).collect(); + + for sd in &split_selection_descs { + if sd.left.col > rightmost_col || sd.right.col < leftmost_col { + // If this selection is out of bounds, exclude this line + continue; + } + + ret_selection_descs.push(SelectionDesc { + left: AnchorPosition { + row: sd.left.row, + col: leftmost_col, + }, + right: AnchorPosition { + row: sd.right.row, + col: rightmost_col, + }, + }); + // The left- and right-most col + + // let subselection_descs + } + + set_selections_desc(&ret_selection_descs[..])?; + + Ok(ret_selection_descs) +} diff --git a/src/main.rs b/src/main.rs index a75eab6..e2d1333 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ // TODO: Remove #![allow(dead_code, unused_imports)] +mod box_; mod errors; mod math_eval; mod set; @@ -51,6 +52,8 @@ enum Commands { // Xargs(xargs::Options), #[clap(about = "Pass each selection null terminated to a command")] Stdin(stdin::Options), + #[clap(about = "Make boxes out of selections", visible_aliases = &["square"])] + Box_(box_::Options), } fn main() { @@ -86,5 +89,6 @@ fn run() -> Result { Commands::Set(o) => set::set(o), // Commands::Xargs(o) => xargs::xargs(o), Commands::Stdin(o) => stdin::stdin(o), + Commands::Box_(o) => box_::box_(o), } } diff --git a/src/math_eval.rs b/src/math_eval.rs index 1cc3f94..61667c2 100644 --- a/src/math_eval.rs +++ b/src/math_eval.rs @@ -2,6 +2,8 @@ use evalexpr::{eval, Value}; use kakplugin::{get_selections, open_command_fifo, KakError}; use std::io::Write; +// TODO: Context for log() and others + #[derive(clap::StructOpt, Debug)] pub struct Options; pub fn math_eval(_options: &Options) -> Result { diff --git a/src/stdin.rs b/src/stdin.rs index 23ec5de..a52d6e4 100644 --- a/src/stdin.rs +++ b/src/stdin.rs @@ -19,7 +19,6 @@ pub fn stdin(options: &Options) -> Result { let mut child_stdin = child.stdin.take().expect("Failed to open stdin"); let handle = std::thread::spawn(move || -> Result<(), KakError> { for s in get_selections_with_desc()? { - eprintln!("Got selection {}", s.content); write!(child_stdin, "{}\0", s.content)?; } Ok(()) diff --git a/src/trim.rs b/src/trim.rs index facee17..fd15adf 100644 --- a/src/trim.rs +++ b/src/trim.rs @@ -39,7 +39,6 @@ pub fn trim(options: &Options) -> Result { } if !options.no_preserve_newline && s.ends_with('\n') { - eprintln!("Adding newline: {s:?}"); new_string.to_owned() + "\n" } else { new_string.to_owned() diff --git a/src/xargs.rs b/src/xargs.rs index 7858d15..fb3be44 100644 --- a/src/xargs.rs +++ b/src/xargs.rs @@ -20,14 +20,11 @@ pub fn xargs(options: &Options) -> Result { let mut stdin = child.stdin.take().expect("Failed to open stdin"); let handle = std::thread::spawn(move || -> Result<(), KakError> { for s in get_selections_with_desc()? { - eprintln!("Got selection {}", s.content); write!(stdin, "{}\0", s.content)?; } Ok(()) }); - eprintln!("About t oreadvv"); - set_selections( BufReader::new( child