feat: impl simple run plugin

This commit is contained in:
imgurbot12 2023-07-24 21:53:23 -07:00
parent 20ced56137
commit 41c7c65528
6 changed files with 103 additions and 4 deletions

View File

@ -2,5 +2,8 @@
resolver = "2" resolver = "2"
members = [ members = [
"rmenu", "rmenu",
"rmenu-plugin" "rmenu-plugin",
"plugin-run",
"plugin-desktop",
"rtest",
] ]

View File

@ -0,0 +1,8 @@
[package]
name = "desktop"
version = "0.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

11
plugin-run/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "run"
version = "0.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rmenu-plugin = { version = "0.0.0", path = "../rmenu-plugin" }
serde_json = "1.0.103"
walkdir = "2.3.3"

64
plugin-run/src/main.rs Normal file
View File

@ -0,0 +1,64 @@
use std::env;
use std::os::unix::fs::PermissionsExt;
use rmenu_plugin::Entry;
use walkdir::{DirEntry, WalkDir};
static PATH: &'static str = "PATH";
static DEFAULT_PATH: &'static str = "/bin:/usr/bin:/usr/sbin";
static EXEC_FLAG: u32 = 0o111;
/// Retrieve Search Paths from OS-VAR or Default
fn bin_paths() -> Vec<String> {
env::var(PATH)
.unwrap_or_else(|_| DEFAULT_PATH.to_string())
.split(":")
.map(|s| s.to_string())
.collect()
}
/// Ignore Entry if Hidden or Filename contains a `.`
fn should_ignore(entry: &DirEntry) -> bool {
entry
.file_name()
.to_str()
.map(|s| s.contains("."))
.unwrap_or(false)
}
/// Retrieve Binaries for the Specified Paths
fn find_binaries(path: String) -> Vec<Entry> {
WalkDir::new(path)
.follow_links(true)
.into_iter()
.filter_entry(|e| !should_ignore(e))
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file())
.filter(|e| {
e.metadata()
.map(|m| m.permissions().mode() & EXEC_FLAG != 0)
.unwrap_or(false)
})
.map(|e| {
let path = e.path().to_string_lossy();
Entry::new(&e.file_name().to_string_lossy(), &path, Some(&path))
})
.collect()
}
fn main() {
// collect entries for sorting
let mut entries: Vec<Entry> = bin_paths()
.into_iter()
.map(find_binaries)
.flatten()
.collect();
// sort entries and render to json
entries.sort_by_cached_key(|e| e.name.clone());
entries
.into_iter()
.map(|e| serde_json::to_string(&e))
.filter_map(|r| r.ok())
.map(|s| println!("{}", s))
.last();
}

View File

@ -13,6 +13,16 @@ pub struct Action {
pub comment: Option<String>, pub comment: Option<String>,
} }
impl Action {
pub fn new(exec: &str) -> Self {
Self {
name: "main".to_string(),
exec: exec.to_string(),
comment: None,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Entry { pub struct Entry {
pub name: String, pub name: String,
@ -22,11 +32,11 @@ pub struct Entry {
} }
impl Entry { impl Entry {
pub fn new(name: &str) -> Self { pub fn new(name: &str, action: &str, comment: Option<&str>) -> Self {
Self { Self {
name: name.to_owned(), name: name.to_owned(),
actions: Default::default(), actions: vec![Action::new(action)],
comment: Default::default(), comment: comment.map(|c| c.to_owned()),
icon: Default::default(), icon: Default::default(),
} }
} }