From e3ee26f8b34476fef3affa4635b6cdaa1d11e39c Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Mon, 21 Apr 2025 22:00:09 +0200 Subject: [PATCH] add dmenu support --- examples/dmenu.sh | 1 + src/lib/config.rs | 2 +- src/lib/gui.rs | 5 +++- src/lib/mode.rs | 75 ++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/examples/dmenu.sh b/examples/dmenu.sh index 9157161..50991d4 100755 --- a/examples/dmenu.sh +++ b/examples/dmenu.sh @@ -7,6 +7,7 @@ Option 3" # Pipe options to wofi and capture the selection selection=$(echo "$options" | cargo run -- --show dmenu) +#selection=$(echo "$options" | wofi --show dmenu) # Do something with the selection echo "You selected: $selection" diff --git a/src/lib/config.rs b/src/lib/config.rs index b1ca6e2..5b6d31e 100644 --- a/src/lib/config.rs +++ b/src/lib/config.rs @@ -622,7 +622,7 @@ pub fn default_fuzzy_min_length() -> Option { #[allow(clippy::unnecessary_wraps)] #[must_use] pub fn default_fuzzy_min_score() -> Option { - Some(0.1) + Some(0.0) } // allowed because option is needed for serde macro diff --git a/src/lib/gui.rs b/src/lib/gui.rs index 7204a8f..0de79b4 100644 --- a/src/lib/gui.rs +++ b/src/lib/gui.rs @@ -902,7 +902,7 @@ fn filter_widgets( score > config .fuzzy_min_score - .unwrap_or(config::default_fuzzy_min_score().unwrap_or(0.0)), + .unwrap_or(config::default_fuzzy_min_score().unwrap_or(0.0)) && score > 0.0, ) } MatchMethod::Contains => { @@ -922,6 +922,9 @@ fn filter_widgets( } }; + + log::debug!("menu item {}, search score {}", menu_item_search, search_sort_score); + menu_item.search_sort_score = search_sort_score; flowbox_child.set_visible(visible); } diff --git a/src/lib/mode.rs b/src/lib/mode.rs index 38c119b..b25b6d2 100644 --- a/src/lib/mode.rs +++ b/src/lib/mode.rs @@ -3,18 +3,19 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::{env, fmt, fs, io}; -use anyhow::Context; -use freedesktop_file_parser::EntryType; -use regex::Regex; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - use crate::config::{Config, expand_path}; use crate::desktop::{ - default_icon, find_desktop_files, get_locale_variants, lookup_name_with_locale, + DesktopError, default_icon, find_desktop_files, get_locale_variants, lookup_name_with_locale, }; use crate::gui; use crate::gui::{ItemProvider, MenuItem}; +use anyhow::Context; +use freedesktop_file_parser::EntryType; +use gtk4::AccessibleRole::Menu; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::io::Read; #[derive(Debug)] pub enum ModeError { @@ -22,6 +23,8 @@ pub enum ModeError { MissingAction, RunError(String), MissingCache, + StdInReadFail, + InvalidSelection, } impl fmt::Display for ModeError { @@ -31,6 +34,8 @@ impl fmt::Display for ModeError { ModeError::MissingAction => write!(f, "MissingAction"), ModeError::RunError(s) => write!(f, "RunError, {s}"), ModeError::MissingCache => write!(f, "MissingCache"), + ModeError::StdInReadFail => write!(f, "StdInReadFail"), + &ModeError::InvalidSelection => write!(f, "InvalidSelection"), } } } @@ -306,7 +311,7 @@ struct MathProvider { menu_item_data: T, } -impl MathProvider { +impl MathProvider { fn new(menu_item_data: T) -> Self { Self { menu_item_data } } @@ -355,6 +360,47 @@ impl ItemProvider for MathProvider { } } +#[derive(Clone)] +struct DMenuProvider { + items: Vec>, +} + +impl DMenuProvider { + fn new() -> Result { + let mut input = String::new(); + io::stdin() + .read_to_string(&mut input) + .map_err(|e| ModeError::StdInReadFail)?; + + let items: Vec> = input + .lines() + .map(String::from) + .map(|s| MenuItem { + label: s, + icon_path: None, + action: None, + sub_elements: vec![], + working_dir: None, + initial_sort_score: 0, + search_sort_score: 0.0, + data: None, + }) + .collect(); + + Ok(Self { items }) + } +} + +impl ItemProvider for DMenuProvider { + fn get_elements(&mut self, _: Option<&str>) -> Vec> { + self.items.clone() + } + + fn get_sub_elements(&mut self, _: &MenuItem) -> Option>> { + None + } +} + #[derive(Debug, Clone, PartialEq)] enum AutoRunType { Math, @@ -509,8 +555,17 @@ pub fn math(config: &Config) { /// # Errors /// /// todo -pub fn dmenu(_: &Config) -> Result<(), ModeError> { - Ok(()) +pub fn dmenu(config: &Config) -> Result<(), ModeError> { + let provider = DMenuProvider::new()?; + + let selection_result = gui::show(config.clone(), provider); + match selection_result { + Ok(s) => { + println!("{}", s.label); + Ok(()) + } + Err(_) => Err(ModeError::InvalidSelection), + } } fn update_drun_cache_and_run(