diff --git a/src/errors.rs b/src/errors.rs index 1cc8c07..2b29653 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,7 +7,7 @@ impl From for KakMessage { fn from(err: std::io::Error) -> Self { Self( "Error writing to fifo".to_string(), - Some(format!("{:?}", err)), + Some(format!("{}", err)), ) } } diff --git a/src/main.rs b/src/main.rs index 1e6c890..e543e63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ #![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)] -#![allow(dead_code, unused_imports)] +// #![allow(dead_code, unused_imports)] mod errors; mod shuf; mod sort; +mod uniq; use clap::{Parser, Subcommand}; use errors::KakMessage; use shuf::ShufOptions; @@ -14,6 +15,7 @@ use std::{ io::Write, str::FromStr, }; +use uniq::UniqOptions; #[derive(Parser, Debug)] #[clap(about, version, author)] @@ -31,6 +33,7 @@ struct Cli { enum Commands { Sort(SortOptions), Shuf(ShufOptions), + Uniq(UniqOptions), } #[derive(PartialEq, PartialOrd, Ord, Eq, Debug)] @@ -103,10 +106,6 @@ impl SelectionDesc { } } -// impl PartialOrd for SelectionDesc { -// fn cmp() {} -// } - fn main() { let msg = match run() { Ok(msg) => msg, @@ -122,7 +121,7 @@ fn main() { }; if let Err(e) = send_message(&msg) { - println!("{:?}", e); + println!("{}", e); } } @@ -146,13 +145,14 @@ fn run() -> Result { let options = Cli::try_parse().map_err(|e| { KakMessage( "Error parsing arguments".to_string(), - Some(format!("Could not parse: {:?}", e)), + Some(format!("Could not parse: {}", e)), ) })?; match &options.command { Commands::Sort(sort_options) => sort::sort(sort_options), Commands::Shuf(shuf_options) => shuf::shuf(shuf_options), + Commands::Uniq(uniq_options) => uniq::uniq(uniq_options), } } diff --git a/src/sort.rs b/src/sort.rs index 5e8ea3b..82b901a 100644 --- a/src/sort.rs +++ b/src/sort.rs @@ -1,6 +1,5 @@ use crate::{kak_response, open_command_fifo, KakMessage, SelectionDesc}; use alphanumeric_sort::compare_str; -use rand::{seq::SliceRandom, thread_rng}; use regex::Regex; use std::{cmp::Ordering, io::Write, str::FromStr}; @@ -11,7 +10,7 @@ pub struct SortOptions { #[clap(short = 's', long)] subselections_register: Option, // TODO: Can we invert a boolean? This name is terrible - #[clap(short = 'S', long)] + #[clap(short = 'S', long, parse(try_from_str = invert_bool), default_value_t)] no_skip_whitespace: bool, #[clap(short, long)] lexicographic_sort: bool, @@ -21,6 +20,15 @@ pub struct SortOptions { ignore_case: bool, } +fn invert_bool(s: &str) -> Result { + // Invert the boolean + match s { + "false" => Ok(true), + "true" => Ok(false), + _ => Err("Unparsable boolean value"), + } +} + struct SortableSelection<'a> { /// The content of the selection content: &'a str, @@ -58,9 +66,12 @@ fn get_sortable_selections_subselections<'a, 'b, 'tmp, S: AsRef + std::fmt: let mut subselections = subselections .iter() .zip(subselections_desc.iter()) - .map(|(s, sd)| Ok((s.as_ref(), SelectionDesc::from_str(sd.as_ref())?))) + // Bind selection with associated description + // Sort descriptions so left is always <= right + .map(|(s, sd)| Ok((s.as_ref(), SelectionDesc::from_str(sd.as_ref())?.sort()))) .collect::, KakMessage>>()?; + // Sort subselections by description subselections.sort_by(|(_, ssd_a), (_, ssd_b)| ssd_a.cmp(ssd_b)); // For each selection, check if they contain any subselections @@ -113,6 +124,8 @@ fn to_sortable_selection<'a, 'b>( } pub fn sort(sort_options: &SortOptions) -> Result { + eprintln!("Got sort options: {:?}", sort_options); + let subselections: Option<(Vec, Vec)> = sort_options .subselections_register .map::, Vec), KakMessage>, _>(|_c| {