notif-picker/src/main.rs
Austin Schaefer fe2039c05e Initial commit: mako notification picker for wofi
Reads notification history via makoctl, formats entries as pango markup
with resolved app icons, and pipes them to wofi in dmenu mode for
selection and invocation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 11:50:35 +02:00

75 lines
2.1 KiB
Rust

mod format;
mod icon;
mod notification;
use std::io::Write;
use std::process::{Command, Stdio};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let notifications = notification::history()?;
if notifications.is_empty() {
return Ok(());
}
let entries: Vec<String> = notifications
.iter()
.map(|n| {
let app_name = n.app_name.as_deref().unwrap_or("unknown");
let summary = n.summary.as_deref().unwrap_or("");
let body = n.body.as_deref().unwrap_or("");
let text = format::entry_text(app_name, summary, body);
match icon::resolve(
n.app_icon.as_deref(),
n.desktop_entry.as_deref(),
n.app_name.as_deref(),
) {
Some(path) => format!("img:{}:text:{text}", path.display()),
None => text,
}
})
.collect();
let Some(index) = prompt_selection(&entries)? else {
return Ok(());
};
if let Some(notification) = notifications.get(index) {
notification::invoke(notification.id)?;
}
Ok(())
}
/// Run wofi in dmenu mode with the given entries and return the selected
/// index, or `None` if the user cancelled (Escape / clicked outside).
fn prompt_selection(entries: &[String]) -> Result<Option<usize>, Box<dyn std::error::Error>> {
let mut child = Command::new("wofi")
.args([
"--dmenu",
"-p",
"Notifications",
"-D",
"dmenu-print_line_num=true",
])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let mut stdin = child.stdin.take().expect("stdin was piped");
stdin.write_all(entries.join("\n").as_bytes())?;
drop(stdin);
let output = child.wait_with_output()?;
if !output.status.success() {
return Ok(None);
}
let selection = String::from_utf8(output.stdout)?;
let selection = selection.trim();
if selection.is_empty() {
return Ok(None);
}
Ok(selection.parse::<usize>().ok())
}