Waste part of my life on stupid cows

This commit is contained in:
Austen Adler 2022-10-02 15:37:28 -04:00
parent e0be452bdb
commit cf6568834c

View File

@ -6,7 +6,11 @@ use kakplugin::{
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use linked_hash_set::LinkedHashSet; use linked_hash_set::LinkedHashSet;
use regex::Regex; use regex::Regex;
use std::{io::Write, str::FromStr}; use std::{
borrow::{Borrow, Cow},
io::Write,
str::FromStr,
};
#[derive(clap::StructOpt, Debug)] #[derive(clap::StructOpt, Debug)]
pub struct Options { pub struct Options {
@ -71,7 +75,8 @@ pub fn set(options: &Options) -> Result<String, KakError> {
// Get the selections for the left register and the right register, depending on the arguments // Get the selections for the left register and the right register, depending on the arguments
// Underscore is a special case. We will treat it as the current selection // Underscore is a special case. We will treat it as the current selection
let (left_selections, right_selections) = match (&left_register, &right_register) { let (left_selections, right_selections): (Vec<Cow<str>>, Vec<Cow<str>>) = {
let (l, r): (Vec<Selection>, Vec<Selection>) = match (&left_register, &right_register) {
(Register::Underscore, r) => { (Register::Underscore, r) => {
let l_selections = get_selections(None)?; let l_selections = get_selections(None)?;
let r_selections = get_selections(Some(&format!("\"{r}z")))?; let r_selections = get_selections(Some(&format!("\"{r}z")))?;
@ -91,26 +96,33 @@ pub fn set(options: &Options) -> Result<String, KakError> {
(l_selections, r_selections) (l_selections, r_selections)
} }
}; };
(
l.into_iter().map(|s| Cow::Owned(s)).collect(),
r.into_iter().map(|s| Cow::Owned(s)).collect(),
)
};
// Get the frequency of each selection. The count does not matter as much as presence // Get the frequency of each selection. The count does not matter as much as presence
// Count is used only for compare // Count is used only for compare
let (left_ordered_counts, right_ordered_counts) = ( let (left_ordered_counts, right_ordered_counts) = (
to_ordered_counts(options, left_selections), to_ordered_counts(options, &left_selections[..]),
to_ordered_counts(options, right_selections), to_ordered_counts(options, &right_selections[..]),
); );
// Get an ordered set of every key for each register // Get an ordered set of every key for each register
let (left_keys, right_keys) = ( let (left_keys, right_keys) = (
left_ordered_counts left_ordered_counts
.keys() .keys()
.collect::<LinkedHashSet<&Selection>>(), .map(|c| Cow::Borrowed(c.borrow()))
.collect(),
right_ordered_counts right_ordered_counts
.keys() .keys()
.collect::<LinkedHashSet<&Selection>>(), .map(|c| Cow::Borrowed(c.borrow()))
.collect(),
); );
// Run the actual set operation // Run the actual set operation
let result = key_set_operation(&operation, &left_keys, &right_keys); let result = key_set_operation(&operation, left_keys, right_keys);
match &operation { match &operation {
Operation::Compare => compare( Operation::Compare => compare(
@ -149,9 +161,9 @@ pub fn set(options: &Options) -> Result<String, KakError> {
} }
/// Reduces selections to those that are in the `key_set_operation_result` /// Reduces selections to those that are in the `key_set_operation_result`
fn reduce_selections( fn reduce_selections<'sel>(
options: &Options, options: &Options,
key_set_operation_result: &LinkedHashSet<&Selection>, key_set_operation_result: &LinkedHashSet<Cow<'sel, str>>,
) -> Result<(), KakError> { ) -> Result<(), KakError> {
// The registers should have been read in a draft context // The registers should have been read in a draft context
// So the current selection will be unmodified // So the current selection will be unmodified
@ -162,7 +174,7 @@ fn reduce_selections(
// Since key_set_operation_result contains elements that should be in the resulting set, // Since key_set_operation_result contains elements that should be in the resulting set,
// we can just use contains here // we can just use contains here
let key = crate::utils::get_key( let key = crate::utils::get_key(
&swd.content, Cow::Owned(swd.content),
options.skip_whitespace, options.skip_whitespace,
options.regex.as_ref(), options.regex.as_ref(),
options.ignore_case, options.ignore_case,
@ -178,7 +190,7 @@ fn reduce_selections(
Ok(()) Ok(())
} }
fn print_result(key_set_operation_result: &LinkedHashSet<&Selection>) -> Result<(), KakError> { fn print_result(key_set_operation_result: &LinkedHashSet<Cow<str>>) -> Result<(), KakError> {
// Manually set selections so we don't have to allocate a string // Manually set selections so we don't have to allocate a string
let mut f = kakplugin::open_command_fifo()?; let mut f = kakplugin::open_command_fifo()?;
@ -207,12 +219,12 @@ fn print_result(key_set_operation_result: &LinkedHashSet<&Selection>) -> Result<
Ok(()) Ok(())
} }
fn compare( fn compare<'sel>(
left_register: Register, left_register: Register,
right_register: Register, right_register: Register,
key_set_operation_result: &LinkedHashSet<&Selection>, key_set_operation_result: &LinkedHashSet<Cow<'sel, str>>,
left_ordered_counts: &LinkedHashMap<Selection, usize>, left_ordered_counts: &LinkedHashMap<Cow<'sel, str>, usize>,
right_ordered_counts: &LinkedHashMap<Selection, usize>, right_ordered_counts: &LinkedHashMap<Cow<'sel, str>, usize>,
) -> Result<(), KakError> { ) -> Result<(), KakError> {
// Manually set selections so we don't have to allocate a string // Manually set selections so we don't have to allocate a string
let mut f = kakplugin::open_command_fifo()?; let mut f = kakplugin::open_command_fifo()?;
@ -232,8 +244,8 @@ fn compare(
)?; )?;
for k in key_set_operation_result { for k in key_set_operation_result {
let left_count = left_ordered_counts.get(k as &str).unwrap_or(&0); let left_count = left_ordered_counts.get(k).unwrap_or(&0);
let right_count = right_ordered_counts.get(k as &str).unwrap_or(&0); let right_count = right_ordered_counts.get(k).unwrap_or(&0);
write!( write!(
f, f,
@ -263,12 +275,15 @@ fn compare(
Ok(()) Ok(())
} }
fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<Selection, usize> { fn to_ordered_counts<'sel>(
options: &Options,
sels: &'sel [Cow<'sel, str>],
) -> LinkedHashMap<Cow<'sel, str>, usize> {
let mut ret = LinkedHashMap::new(); let mut ret = LinkedHashMap::new();
for i in sels { for i in sels {
let key = crate::utils::get_key( let key = crate::utils::get_key(
&i, Cow::Borrowed(&*i),
options.skip_whitespace, options.skip_whitespace,
options.regex.as_ref(), options.regex.as_ref(),
options.ignore_case, options.ignore_case,
@ -285,29 +300,28 @@ fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<S
ret ret
} }
/// Performs an `Operation` on some set of keys /// Performs an `Operation` on some set of keys. This returns a a hashset of the operations
/// * `operation` - The operation to perform /// * `operation` - The operation to perform
/// * `left_keys` - The set on the left side of the operator /// * `left_keys` - The set on the left side of the operator
/// * `right_keys` - The set on the right side of the operator /// * `right_keys` - The set on the right side of the operator
fn key_set_operation<'a>( fn key_set_operation<'a, 'sel>(
operation: &Operation, operation: &'a Operation,
left_keys: &LinkedHashSet<&'a Selection>, left_keys: LinkedHashSet<Cow<'sel, str>>,
right_keys: &LinkedHashSet<&'a Selection>, right_keys: LinkedHashSet<Cow<'sel, str>>,
) -> LinkedHashSet<&'a Selection> { ) -> LinkedHashSet<Cow<'sel, str>> {
match operation { match operation {
Operation::Intersect => left_keys Operation::Intersect => left_keys
.intersection(right_keys) .intersection(&right_keys)
// .into_iter() .map(|s| Cow::Borrowed(s.borrow()))
.copied()
.collect(), .collect(),
Operation::Subtract => left_keys Operation::Subtract => left_keys
.difference(right_keys) .difference(&right_keys)
.into_iter() .map(|s| Cow::Borrowed(s.borrow()))
.copied()
.collect(), .collect(),
Operation::Compare | Operation::Union => { Operation::Compare | Operation::Union => left_keys
left_keys.union(right_keys).into_iter().copied().collect() .union(&right_keys)
} // TODO: Symmetric difference? .map(|s| Cow::Borrowed(s.borrow()))
.collect(), // TODO: Symmetric difference?
} }
} }