Use draft selections to not mangle the current selection

This commit is contained in:
Austen Adler 2022-07-07 01:24:21 -04:00
parent b6114b607c
commit 9d982a2723
2 changed files with 38 additions and 17 deletions

View File

@ -180,6 +180,23 @@ where
cmd(&format!("execute-keys '\"{}z'", r.as_ref().kak_escaped())) cmd(&format!("execute-keys '\"{}z'", r.as_ref().kak_escaped()))
} }
pub fn get_register_selections<R>(r: R) -> Result<Vec<Selection>, KakError>
where
R: AsRef<Register>,
{
cmd(&format!(
r#"
evaluate-commands -draft %{{
execute-keys '\"{}z';
echo -quoting shell -to-file {} -- %val{{selections}};
}}"#,
r.as_ref().kak_escaped(),
get_var("kak_response_fifo")?
))?;
let selections = shellwords::split(&fs::read_to_string(&get_var("kak_response_fifo")?)?)?;
Ok(selections)
}
/// # Errors /// # Errors
/// ///
/// Will return `Err` if command fifo could not be opened or written to /// Will return `Err` if command fifo could not be opened or written to

View File

@ -1,8 +1,8 @@
// use crate::utils; // use crate::utils;
use clap::ArgEnum; use clap::ArgEnum;
use kakplugin::{ use kakplugin::{
get_selections, get_selections_with_desc, set_selections, set_selections_desc, types::Register, get_register_selections, get_selections, get_selections_with_desc, set_selections,
KakError, Selection, SelectionWithDesc, set_selections_desc, types::Register, KakError, Selection, SelectionWithDesc,
}; };
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use linked_hash_set::LinkedHashSet; use linked_hash_set::LinkedHashSet;
@ -66,38 +66,41 @@ impl FromStr for Operation {
} }
pub fn set(options: &Options) -> Result<String, KakError> { pub fn set(options: &Options) -> Result<String, KakError> {
// 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[..])?;
// 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) = match (&left_register, &right_register) {
(Register::Underscore, r) => { (Register::Underscore, r) => {
let l_selections = get_selections()?; let l_selections = get_selections()?;
kakplugin::restore_register(r)?; let r_selections = get_register_selections(r)?;
let r_selections = get_selections()?;
(l_selections, r_selections) (l_selections, r_selections)
} }
(l, Register::Underscore) => { (l, Register::Underscore) => {
let r_selections = get_selections()?; let r_selections = get_selections()?;
kakplugin::restore_register(l)?; let l_selections = get_register_selections(l)?;
let l_selections = get_selections()?;
(l_selections, r_selections) (l_selections, r_selections)
} }
(l, r) => { (l, r) => {
kakplugin::restore_register(l)?; let l_selections = get_register_selections(l)?;
let l_selections = get_selections()?; let r_selections = get_register_selections(r)?;
kakplugin::restore_register(r)?;
let r_selections = get_selections()?;
(l_selections, r_selections) (l_selections, r_selections)
} }
}; };
// Get the frequency of each selection. The count does not matter as much as presence
// 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
let (left_keys, right_keys) = ( let (left_keys, right_keys) = (
left_ordered_counts left_ordered_counts
.keys() .keys()
@ -107,6 +110,7 @@ pub fn set(options: &Options) -> Result<String, KakError> {
.collect::<LinkedHashSet<&Selection>>(), .collect::<LinkedHashSet<&Selection>>(),
); );
// 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 {
@ -118,12 +122,16 @@ pub fn set(options: &Options) -> Result<String, KakError> {
&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
// 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
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
print_result(&result)? print_result(&result)?
} }
} }
@ -146,18 +154,17 @@ fn reduce_selections(
options: &Options, options: &Options,
key_set_operation_result: &LinkedHashSet<&Selection>, key_set_operation_result: &LinkedHashSet<&Selection>,
) -> Result<(), KakError> { ) -> Result<(), KakError> {
kakplugin::restore_register(&Register::Caret)?; // The registers should have been read in a draft context
// So the current selection will be unmodified
let selections_with_desc = { let selections_with_desc = {
let mut r = get_selections_with_desc()?; let mut r = get_selections_with_desc()?;
r.sort_by_key(|s| s.desc.sort()); r.sort_by_key(|s| s.desc.sort());
r r
}; };
eprintln!("Key set operation result: {:?}", key_set_operation_result);
set_selections_desc(selections_with_desc.into_iter().filter_map(|swd| { set_selections_desc(selections_with_desc.into_iter().filter_map(|swd| {
// Does not matter if the operation was - or & // Does not matter if the operation was - or &
// Since key_set_operation_result contains elements that should be in the 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, &swd.content,
@ -169,7 +176,6 @@ fn reduce_selections(
if key_set_operation_result.contains(&key) { if key_set_operation_result.contains(&key) {
Some(swd.desc) Some(swd.desc)
} else { } else {
eprintln!("Key {key} not found");
None None
} }
}))?; }))?;
@ -246,8 +252,6 @@ fn compare(
}, },
left_count, left_count,
right_count, right_count,
// TODO: Do we want to escape the \n to \\n?
// kakplugin::escape(k.replace('\n', "\\n")),
kakplugin::escape(k), kakplugin::escape(k),
)?; )?;
} }