Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cf6568834c |
112
src/set.rs
112
src/set.rs
@ -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,46 +75,54 @@ 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>>) = {
|
||||||
(Register::Underscore, r) => {
|
let (l, r): (Vec<Selection>, Vec<Selection>) = match (&left_register, &right_register) {
|
||||||
let l_selections = get_selections(None)?;
|
(Register::Underscore, r) => {
|
||||||
let r_selections = get_selections(Some(&format!("\"{r}z")))?;
|
let l_selections = get_selections(None)?;
|
||||||
|
let r_selections = get_selections(Some(&format!("\"{r}z")))?;
|
||||||
|
|
||||||
(l_selections, r_selections)
|
(l_selections, r_selections)
|
||||||
}
|
}
|
||||||
(l, Register::Underscore) => {
|
(l, Register::Underscore) => {
|
||||||
let r_selections = get_selections(None)?;
|
let r_selections = get_selections(None)?;
|
||||||
let l_selections = get_selections(Some(&format!("\"{l}z")))?;
|
let l_selections = get_selections(Some(&format!("\"{l}z")))?;
|
||||||
|
|
||||||
(l_selections, r_selections)
|
(l_selections, r_selections)
|
||||||
}
|
}
|
||||||
(l, r) => {
|
(l, r) => {
|
||||||
let l_selections = get_selections(Some(&format!("\"{l}z")))?;
|
let l_selections = get_selections(Some(&format!("\"{l}z")))?;
|
||||||
let r_selections = get_selections(Some(&format!("\"{r}z")))?;
|
let r_selections = get_selections(Some(&format!("\"{r}z")))?;
|
||||||
|
|
||||||
(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?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user