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)]
|
||||
pub enum KakError {
|
||||
@ -16,10 +16,14 @@ pub enum KakError {
|
||||
NotImplemented(&'static str),
|
||||
/// Custom error string
|
||||
Custom(String),
|
||||
/// Custom static error string
|
||||
CustomStatic(&'static str),
|
||||
/// The selections/selections_desc list passed was empty
|
||||
SetEmptySelections,
|
||||
}
|
||||
|
||||
impl std::error::Error for KakError {}
|
||||
|
||||
impl KakError {
|
||||
pub fn details(&self) -> String {
|
||||
match self {
|
||||
@ -30,6 +34,7 @@ impl KakError {
|
||||
Self::Io(e) => format!("{e:?}"),
|
||||
Self::NotImplemented(e) => e.to_string(),
|
||||
Self::Custom(s) => s.clone(),
|
||||
Self::CustomStatic(s) => s.to_string(),
|
||||
Self::SetEmptySelections => {
|
||||
String::from("Attempted to set selections/selections_desc to empty list")
|
||||
}
|
||||
@ -37,22 +42,23 @@ impl KakError {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for KakError {
|
||||
fn to_string(&self) -> String {
|
||||
format!(
|
||||
"Error: {}",
|
||||
match self {
|
||||
Self::EnvVarNotSet(_) => "env var not set",
|
||||
Self::EnvVarUnicode(_) => "env var not unicode",
|
||||
Self::Parse(_) => "Could not parse",
|
||||
Self::KakResponse(_) => "Invalid kak response",
|
||||
Self::Io(_) => "IO error",
|
||||
Self::NotImplemented(_) => "Not Implemented",
|
||||
Self::Custom(s) => s,
|
||||
Self::SetEmptySelections =>
|
||||
"Attempted to set selections/selections_desc to empty list",
|
||||
}
|
||||
)
|
||||
impl Display for KakError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error: ")?;
|
||||
match self {
|
||||
Self::EnvVarNotSet(_) => write!(f, "env var not set"),
|
||||
Self::EnvVarUnicode(_) => write!(f, "env var not unicode"),
|
||||
Self::Parse(_) => write!(f, "Could not parse"),
|
||||
Self::KakResponse(_) => write!(f, "Invalid kak response"),
|
||||
Self::Io(_) => write!(f, "IO error"),
|
||||
Self::NotImplemented(_) => write!(f, "Not Implemented"),
|
||||
Self::Custom(s) => write!(f, "{}", s),
|
||||
Self::CustomStatic(s) => write!(f, "{}", s),
|
||||
Self::SetEmptySelections => write!(
|
||||
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 {
|
||||
Numeric0,
|
||||
Numeric1,
|
||||
|
@ -40,11 +40,12 @@ pub fn incr(options: &Options, should_increment: bool) -> Result<String, KakErro
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"{} {} selections by {} ({} errors)",
|
||||
"{} {} selections by {} ({} error{})",
|
||||
if should_increment { "Incr" } else { "Decr" },
|
||||
selections.len().saturating_sub(err_count),
|
||||
options.amount,
|
||||
err_count,
|
||||
if err_count == 1 { "" } else { "s" }
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#![allow(dead_code, unused_imports)]
|
||||
#![feature(slice_group_by)]
|
||||
#![feature(slice_take)]
|
||||
#![feature(array_chunks)]
|
||||
|
||||
mod box_;
|
||||
mod errors;
|
||||
@ -22,6 +23,7 @@ mod stdin;
|
||||
mod trim;
|
||||
mod uniq;
|
||||
mod utils;
|
||||
mod xlookup;
|
||||
// mod xargs;
|
||||
use clap::{Parser, Subcommand};
|
||||
use kakplugin::{display_message, get_var, KakError};
|
||||
@ -63,7 +65,11 @@ enum Commands {
|
||||
Stdin(stdin::Options),
|
||||
#[clap(about = "Make boxes out of selections", visible_aliases = &["square"])]
|
||||
Box_(box_::Options),
|
||||
#[clap(about = "Map selections based on a register", visible_aliases = &["vlookup"])]
|
||||
Xlookup(xlookup::Options),
|
||||
#[clap(about = "Increment selections")]
|
||||
Decr(incr::Options),
|
||||
#[clap(about = "Decrement selections")]
|
||||
Incr(incr::Options),
|
||||
}
|
||||
|
||||
@ -114,6 +120,7 @@ fn run() -> Result<String, KakError> {
|
||||
// Commands::Xargs(o) => xargs::xargs(o),
|
||||
Commands::Stdin(o) => stdin::stdin(o),
|
||||
Commands::Box_(o) => box_::box_(o),
|
||||
Commands::Xlookup(o) => xlookup::xlookup(o),
|
||||
Commands::Incr(o) => incr::incr(o, true),
|
||||
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())
|
||||
} else {
|
||||
format!(
|
||||
"Processed {} selections ({} errors)",
|
||||
"Processed {} selections ({} error{})",
|
||||
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