Add xlookup

This commit is contained in:
Austen Adler 2022-09-06 00:28:00 -04:00
parent 3660a35923
commit 6745a8ad5b
6 changed files with 111 additions and 21 deletions

View File

@ -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"
),
}
}
}

View File

@ -325,7 +325,7 @@ impl FromStr for AnchorPosition {
}
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Register {
Numeric0,
Numeric1,

View File

@ -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" }
)
})
}

View File

@ -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),
}

View File

@ -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
View 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)
}
}