Use Cow for set
This commit is contained in:
parent
0642b909c3
commit
c9674e9bf2
67
src/set.rs
67
src/set.rs
@ -1,12 +1,11 @@
|
|||||||
// use crate::utils;
|
// use crate::utils;
|
||||||
use kakplugin::{
|
use kakplugin::{
|
||||||
get_selections, get_selections_with_desc, set_selections_desc, types::Register, KakError,
|
get_selections, get_selections_with_desc, set_selections_desc, types::Register, KakError,
|
||||||
Selection,
|
|
||||||
};
|
};
|
||||||
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::Cow, io::Write, str::FromStr};
|
||||||
|
|
||||||
#[derive(clap::StructOpt, Debug)]
|
#[derive(clap::StructOpt, Debug)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
@ -65,7 +64,7 @@ impl FromStr for Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(options: &Options) -> Result<String, KakError> {
|
pub fn set<'sel>(options: &'_ Options) -> Result<String, KakError> {
|
||||||
// Get the actual operation we are performing
|
// Get the actual operation we are performing
|
||||||
let (left_register, operation, right_register) = parse_arguments(&options.args[..])?;
|
let (left_register, operation, right_register) = parse_arguments(&options.args[..])?;
|
||||||
|
|
||||||
@ -95,63 +94,72 @@ pub fn set(options: &Options) -> Result<String, KakError> {
|
|||||||
// 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(
|
||||||
to_ordered_counts(options, right_selections),
|
options,
|
||||||
|
left_selections.iter().map(|s| s.as_ref()).collect(),
|
||||||
|
),
|
||||||
|
to_ordered_counts(
|
||||||
|
options,
|
||||||
|
right_selections.iter().map(|s| s.as_ref()).collect(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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(|k| -> &str { k.as_ref() })
|
||||||
|
.collect::<LinkedHashSet<&str>>(),
|
||||||
right_ordered_counts
|
right_ordered_counts
|
||||||
.keys()
|
.keys()
|
||||||
.collect::<LinkedHashSet<&Selection>>(),
|
.map(|k| -> &str { k.as_ref() })
|
||||||
|
.collect::<LinkedHashSet<&str>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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);
|
||||||
|
let num_modified = result.len();
|
||||||
|
|
||||||
match &operation {
|
match &operation {
|
||||||
Operation::Compare => compare(
|
Operation::Compare => compare(
|
||||||
left_register,
|
left_register,
|
||||||
right_register,
|
right_register,
|
||||||
&result,
|
result,
|
||||||
&left_ordered_counts,
|
&left_ordered_counts,
|
||||||
&right_ordered_counts,
|
&right_ordered_counts,
|
||||||
)?,
|
)?,
|
||||||
Operation::Union => print_result(&result)?,
|
Operation::Union => print_result(result)?,
|
||||||
// Intersect/subtract will have at most the number of elements in the current selection
|
// Intersect/subtract will have at most the number of elements in the current selection
|
||||||
// If the user operated on the current selection, and we can modify the selection descs inplace, do it
|
// If the user operated on the current selection, and we can modify the selection descs inplace, do it
|
||||||
Operation::Intersect | Operation::Subtract => {
|
Operation::Intersect | Operation::Subtract => {
|
||||||
if left_register == Register::Underscore {
|
if left_register == Register::Underscore {
|
||||||
// If the user asked for an intersection or subtraction from the current selection, we can update selection_descs only
|
// If the user asked for an intersection or subtraction from the current selection, we can update selection_descs only
|
||||||
// For example (current selection) - (contents of register a) allows us to simply deselect some selections
|
// For example (current selection) - (contents of register a) allows us to simply deselect some selections
|
||||||
reduce_selections(options, &result)?;
|
reduce_selections(options, result)?;
|
||||||
} else {
|
} else {
|
||||||
// The user asked for registers that *aren't* the current selection
|
// The user asked for registers that *aren't* the current selection
|
||||||
// This means either registers don't represent the current selection, or the current selection is on the other side
|
// This means either registers don't represent the current selection, or the current selection is on the other side
|
||||||
print_result(&result)?;
|
print_result(result)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match &operation {
|
Ok(match &operation {
|
||||||
Operation::Compare => format!("Compared {} selections", result.len()),
|
Operation::Compare => format!("Compared {} selections", num_modified),
|
||||||
op => format!(
|
op => format!(
|
||||||
"{}{}{} returned {} selections",
|
"{}{}{} returned {} selections",
|
||||||
left_register.to_char(),
|
left_register.to_char(),
|
||||||
op.to_char(),
|
op.to_char(),
|
||||||
right_register.to_char(),
|
right_register.to_char(),
|
||||||
result.len()
|
num_modified
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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, 'a>(
|
||||||
options: &Options,
|
options: &Options,
|
||||||
key_set_operation_result: &LinkedHashSet<&Selection>,
|
key_set_operation_result: LinkedHashSet<&'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
|
||||||
@ -168,8 +176,7 @@ fn reduce_selections(
|
|||||||
options.ignore_case,
|
options.ignore_case,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Do not allocate
|
if key_set_operation_result.contains(key.as_ref()) {
|
||||||
if key_set_operation_result.contains(&key.into_owned()) {
|
|
||||||
Some(swd.desc)
|
Some(swd.desc)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -179,7 +186,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<&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()?;
|
||||||
|
|
||||||
@ -208,12 +215,12 @@ fn print_result(key_set_operation_result: &LinkedHashSet<&Selection>) -> Result<
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare(
|
fn compare<'sel, 'a, 'b>(
|
||||||
left_register: Register,
|
left_register: Register,
|
||||||
right_register: Register,
|
right_register: Register,
|
||||||
key_set_operation_result: &LinkedHashSet<&Selection>,
|
key_set_operation_result: LinkedHashSet<&'b str>,
|
||||||
left_ordered_counts: &LinkedHashMap<Selection, usize>,
|
left_ordered_counts: &'b LinkedHashMap<Cow<'sel, str>, usize>,
|
||||||
right_ordered_counts: &LinkedHashMap<Selection, usize>,
|
right_ordered_counts: &'b 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()?;
|
||||||
@ -264,12 +271,14 @@ fn compare(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<Selection, usize> {
|
fn to_ordered_counts<'sel>(
|
||||||
|
options: &Options,
|
||||||
|
sels: Vec<&'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(
|
||||||
// TODO: Do not allocate
|
|
||||||
&i,
|
&i,
|
||||||
options.skip_whitespace,
|
options.skip_whitespace,
|
||||||
options.regex.as_ref(),
|
options.regex.as_ref(),
|
||||||
@ -282,7 +291,7 @@ fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Do not allocate
|
// TODO: Do not allocate
|
||||||
let entry: &mut usize = ret.entry(key.into_owned()).or_insert(0);
|
let entry: &mut usize = ret.entry(key).or_insert(0);
|
||||||
*entry = entry.saturating_add(1);
|
*entry = entry.saturating_add(1);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
@ -292,11 +301,11 @@ fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<S
|
|||||||
/// * `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<'sel>(
|
||||||
operation: &Operation,
|
operation: &Operation,
|
||||||
left_keys: &LinkedHashSet<&'a Selection>,
|
left_keys: &LinkedHashSet<&'sel str>,
|
||||||
right_keys: &LinkedHashSet<&'a Selection>,
|
right_keys: &LinkedHashSet<&'sel str>,
|
||||||
) -> LinkedHashSet<&'a Selection> {
|
) -> LinkedHashSet<&'sel str> {
|
||||||
match operation {
|
match operation {
|
||||||
Operation::Intersect => left_keys
|
Operation::Intersect => left_keys
|
||||||
.intersection(right_keys)
|
.intersection(right_keys)
|
||||||
|
Loading…
Reference in New Issue
Block a user