Files
anyrun/plugins/kidex/src/lib.rs
2023-04-15 08:02:23 +03:00

151 lines
4.8 KiB
Rust

use abi_stable::std_types::{ROption, RString, RVec};
use anyrun_plugin::{anyrun_interface::HandleResult, *};
use fuzzy_matcher::FuzzyMatcher;
use kidex_common::IndexEntry;
use std::{os::unix::prelude::OsStrExt, process::Command};
pub struct State {
index: Vec<(usize, IndexEntry)>,
selection: Option<IndexEntry>,
}
enum IndexAction {
Open,
CopyPath,
Back,
}
impl From<u64> for IndexAction {
fn from(value: u64) -> Self {
match value {
0 => Self::Open,
1 => Self::CopyPath,
2 => Self::Back,
_ => unreachable!(),
}
}
}
pub fn handler(selection: Match, state: &mut State) -> HandleResult {
match &state.selection {
Some(index_entry) => match selection.id.unwrap().into() {
IndexAction::Open => {
if let Err(why) = Command::new("xdg-open").arg(&index_entry.path).spawn() {
println!("Error running xdg-open: {}", why);
}
HandleResult::Close
}
IndexAction::CopyPath => {
HandleResult::Copy(index_entry.path.clone().into_os_string().as_bytes().into())
}
IndexAction::Back => {
state.selection = None;
HandleResult::Refresh(false)
}
},
None => {
let (_, index_entry) = state
.index
.iter()
.find(|(id, _)| selection.id == ROption::RSome(*id as u64))
.unwrap();
state.selection = Some(index_entry.clone());
HandleResult::Refresh(true)
}
}
}
pub fn init(_config_dir: RString) -> State {
State {
index: match kidex_common::util::get_index(None) {
Ok(index) => index.into_iter().enumerate().collect(),
Err(why) => {
println!("Failed to get kidex index: {}", why);
Vec::new()
}
},
selection: None,
}
}
pub fn get_matches(input: RString, state: &mut State) -> RVec<Match> {
match &state.selection {
Some(index_entry) => {
let path = index_entry.path.to_string_lossy();
vec![
Match {
title: "Open File".into(),
description: ROption::RSome(path.clone().into()),
use_pango: false,
id: ROption::RSome(IndexAction::Open as u64),
icon: ROption::RSome("document-open".into()),
},
Match {
title: "Copy Path".into(),
description: ROption::RSome(path.into()),
use_pango: false,
id: ROption::RSome(IndexAction::CopyPath as u64),
icon: ROption::RSome("edit-copy".into()),
},
Match {
title: "Back".into(),
description: ROption::RNone,
use_pango: false,
id: ROption::RSome(IndexAction::Back as u64),
icon: ROption::RSome("edit-undo".into()),
},
]
.into()
}
None => {
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
let mut index = state
.index
.clone()
.into_iter()
.filter_map(|(id, index_entry)| {
matcher
.fuzzy_match(&index_entry.path.as_os_str().to_string_lossy(), &input)
.map(|val| (index_entry, id, val))
})
.collect::<Vec<_>>();
index.sort_by(|a, b| b.2.cmp(&a.2));
index.truncate(3);
index
.into_iter()
.map(|(entry_index, id, _)| Match {
title: entry_index
.path
.file_name()
.map(|name| name.to_string_lossy().into())
.unwrap_or("N/A".into()),
description: entry_index
.path
.parent()
.map(|path| path.display().to_string().into())
.into(),
use_pango: false,
icon: ROption::RSome(if entry_index.directory {
"folder".into()
} else {
"text-x-generic".into()
}),
id: ROption::RSome(id as u64),
})
.collect()
}
}
}
pub fn info() -> PluginInfo {
PluginInfo {
name: "Kidex".into(),
icon: "folder".into(),
}
}
plugin!(init, info, get_matches, handler, State);