Add xlookup
This commit is contained in:
parent
3660a35923
commit
6745a8ad5b
@ -1,4 +1,4 @@
|
|||||||
use std::num::ParseIntError;
|
use std::{fmt, fmt::Display, num::ParseIntError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum KakError {
|
pub enum KakError {
|
||||||
@ -16,10 +16,14 @@ pub enum KakError {
|
|||||||
NotImplemented(&'static str),
|
NotImplemented(&'static str),
|
||||||
/// Custom error string
|
/// Custom error string
|
||||||
Custom(String),
|
Custom(String),
|
||||||
|
/// Custom static error string
|
||||||
|
CustomStatic(&'static str),
|
||||||
/// The selections/selections_desc list passed was empty
|
/// The selections/selections_desc list passed was empty
|
||||||
SetEmptySelections,
|
SetEmptySelections,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for KakError {}
|
||||||
|
|
||||||
impl KakError {
|
impl KakError {
|
||||||
pub fn details(&self) -> String {
|
pub fn details(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
@ -30,6 +34,7 @@ impl KakError {
|
|||||||
Self::Io(e) => format!("{e:?}"),
|
Self::Io(e) => format!("{e:?}"),
|
||||||
Self::NotImplemented(e) => e.to_string(),
|
Self::NotImplemented(e) => e.to_string(),
|
||||||
Self::Custom(s) => s.clone(),
|
Self::Custom(s) => s.clone(),
|
||||||
|
Self::CustomStatic(s) => s.to_string(),
|
||||||
Self::SetEmptySelections => {
|
Self::SetEmptySelections => {
|
||||||
String::from("Attempted to set selections/selections_desc to empty list")
|
String::from("Attempted to set selections/selections_desc to empty list")
|
||||||
}
|
}
|
||||||
@ -37,22 +42,23 @@ impl KakError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for KakError {
|
impl Display for KakError {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
format!(
|
write!(f, "Error: ")?;
|
||||||
"Error: {}",
|
match self {
|
||||||
match self {
|
Self::EnvVarNotSet(_) => write!(f, "env var not set"),
|
||||||
Self::EnvVarNotSet(_) => "env var not set",
|
Self::EnvVarUnicode(_) => write!(f, "env var not unicode"),
|
||||||
Self::EnvVarUnicode(_) => "env var not unicode",
|
Self::Parse(_) => write!(f, "Could not parse"),
|
||||||
Self::Parse(_) => "Could not parse",
|
Self::KakResponse(_) => write!(f, "Invalid kak response"),
|
||||||
Self::KakResponse(_) => "Invalid kak response",
|
Self::Io(_) => write!(f, "IO error"),
|
||||||
Self::Io(_) => "IO error",
|
Self::NotImplemented(_) => write!(f, "Not Implemented"),
|
||||||
Self::NotImplemented(_) => "Not Implemented",
|
Self::Custom(s) => write!(f, "{}", s),
|
||||||
Self::Custom(s) => s,
|
Self::CustomStatic(s) => write!(f, "{}", s),
|
||||||
Self::SetEmptySelections =>
|
Self::SetEmptySelections => write!(
|
||||||
"Attempted to set selections/selections_desc to empty list",
|
f,
|
||||||
}
|
"Attempted to set selections/selections_desc to empty list"
|
||||||
)
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ impl FromStr for AnchorPosition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum Register {
|
pub enum Register {
|
||||||
Numeric0,
|
Numeric0,
|
||||||
Numeric1,
|
Numeric1,
|
||||||
|
@ -40,11 +40,12 @@ pub fn incr(options: &Options, should_increment: bool) -> Result<String, KakErro
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"{} {} selections by {} ({} errors)",
|
"{} {} selections by {} ({} error{})",
|
||||||
if should_increment { "Incr" } else { "Decr" },
|
if should_increment { "Incr" } else { "Decr" },
|
||||||
selections.len().saturating_sub(err_count),
|
selections.len().saturating_sub(err_count),
|
||||||
options.amount,
|
options.amount,
|
||||||
err_count,
|
err_count,
|
||||||
|
if err_count == 1 { "" } else { "s" }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#![allow(dead_code, unused_imports)]
|
#![allow(dead_code, unused_imports)]
|
||||||
#![feature(slice_group_by)]
|
#![feature(slice_group_by)]
|
||||||
#![feature(slice_take)]
|
#![feature(slice_take)]
|
||||||
|
#![feature(array_chunks)]
|
||||||
|
|
||||||
mod box_;
|
mod box_;
|
||||||
mod errors;
|
mod errors;
|
||||||
@ -22,6 +23,7 @@ mod stdin;
|
|||||||
mod trim;
|
mod trim;
|
||||||
mod uniq;
|
mod uniq;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod xlookup;
|
||||||
// mod xargs;
|
// mod xargs;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use kakplugin::{display_message, get_var, KakError};
|
use kakplugin::{display_message, get_var, KakError};
|
||||||
@ -63,7 +65,11 @@ enum Commands {
|
|||||||
Stdin(stdin::Options),
|
Stdin(stdin::Options),
|
||||||
#[clap(about = "Make boxes out of selections", visible_aliases = &["square"])]
|
#[clap(about = "Make boxes out of selections", visible_aliases = &["square"])]
|
||||||
Box_(box_::Options),
|
Box_(box_::Options),
|
||||||
|
#[clap(about = "Map selections based on a register", visible_aliases = &["vlookup"])]
|
||||||
|
Xlookup(xlookup::Options),
|
||||||
|
#[clap(about = "Increment selections")]
|
||||||
Decr(incr::Options),
|
Decr(incr::Options),
|
||||||
|
#[clap(about = "Decrement selections")]
|
||||||
Incr(incr::Options),
|
Incr(incr::Options),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +120,7 @@ fn run() -> Result<String, KakError> {
|
|||||||
// Commands::Xargs(o) => xargs::xargs(o),
|
// Commands::Xargs(o) => xargs::xargs(o),
|
||||||
Commands::Stdin(o) => stdin::stdin(o),
|
Commands::Stdin(o) => stdin::stdin(o),
|
||||||
Commands::Box_(o) => box_::box_(o),
|
Commands::Box_(o) => box_::box_(o),
|
||||||
|
Commands::Xlookup(o) => xlookup::xlookup(o),
|
||||||
Commands::Incr(o) => incr::incr(o, true),
|
Commands::Incr(o) => incr::incr(o, true),
|
||||||
Commands::Decr(o) => incr::incr(o, false),
|
Commands::Decr(o) => incr::incr(o, false),
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,10 @@ pub fn math_eval(_options: &Options) -> Result<String, KakError> {
|
|||||||
format!("Processed {} selections", selections.len())
|
format!("Processed {} selections", selections.len())
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"Processed {} selections ({} errors)",
|
"Processed {} selections ({} error{})",
|
||||||
selections.len().saturating_sub(err_count),
|
selections.len().saturating_sub(err_count),
|
||||||
err_count
|
err_count,
|
||||||
|
if err_count == 1 { "" } else { "s" }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
75
src/xlookup.rs
Normal file
75
src/xlookup.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use crate::utils::get_hash;
|
||||||
|
use evalexpr::{eval, Value};
|
||||||
|
use kakplugin::{
|
||||||
|
get_selections, open_command_fifo, set_selections, types::Register, KakError, Selection,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
collections::{
|
||||||
|
btree_map::Entry::{Occupied, Vacant},
|
||||||
|
hash_map::DefaultHasher,
|
||||||
|
BTreeMap,
|
||||||
|
},
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
io::Write,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(clap::StructOpt, Debug)]
|
||||||
|
pub struct Options {
|
||||||
|
#[clap(help = "Register with the lookup table")]
|
||||||
|
register: Register,
|
||||||
|
}
|
||||||
|
pub fn xlookup(options: &Options) -> Result<String, KakError> {
|
||||||
|
let lookup_table = build_lookuptable(options.register)?;
|
||||||
|
eprintln!("Lookup table: {lookup_table:#?}");
|
||||||
|
|
||||||
|
let selections = get_selections(None)?;
|
||||||
|
|
||||||
|
let mut err_count: usize = 0;
|
||||||
|
|
||||||
|
set_selections(selections.iter().map(|key| {
|
||||||
|
match lookup_table.get(&get_hash(&key, false, None, false)) {
|
||||||
|
Some(v) => v.to_string(),
|
||||||
|
None => {
|
||||||
|
eprintln!(
|
||||||
|
"Nothing for '{key}' ({})",
|
||||||
|
get_hash(&key, false, None, false)
|
||||||
|
);
|
||||||
|
err_count += 1;
|
||||||
|
String::from("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))?;
|
||||||
|
|
||||||
|
Ok(if err_count == 0 {
|
||||||
|
format!("Xlookup {} selections", selections.len())
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"Xlookup {} selections ({} error{})",
|
||||||
|
selections.len().saturating_sub(err_count),
|
||||||
|
err_count,
|
||||||
|
if err_count == 1 { "" } else { "s" }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_lookuptable(reg: Register) -> Result<BTreeMap<u64, Selection>, KakError> {
|
||||||
|
let mut selections = get_selections(Some(&format!("\"{reg}z")))?;
|
||||||
|
let mut iter = selections.array_chunks_mut();
|
||||||
|
let ret = iter.try_fold(BTreeMap::new(), |mut acc, [key, value]| {
|
||||||
|
match acc.entry(get_hash(&key, false, None, false)) {
|
||||||
|
Occupied(_) => Err(KakError::Custom(format!("Duplicate key '{key}'"))),
|
||||||
|
Vacant(v) => {
|
||||||
|
v.insert(value.to_owned());
|
||||||
|
Ok(acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if !iter.into_remainder().is_empty() {
|
||||||
|
Err(KakError::CustomStatic("Odd number of selections"))
|
||||||
|
} else if ret.is_empty() {
|
||||||
|
Err(KakError::CustomStatic("No selections"))
|
||||||
|
} else {
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user