use std::{ fs::File, io::{self, BufRead}, process::Command, }; use dialoguer::{theme::ColorfulTheme, Select}; fn main() { let sessions = load_sessions(); let selection = Select::with_theme(&ColorfulTheme::default()) .with_prompt("Select session") .default(0) .items(&sessions) .interact() .unwrap(); Command::new(&sessions[selection].exec) .spawn() .expect("failed to run session") .wait() .expect("failed to wait on child"); } fn load_sessions() -> Vec { let wayland_sessions = glob::glob("/usr/share/wayland-sessions/*.desktop") .unwrap() .filter_map(|result| result.ok()) .map(|path| { let mut session_name = None; let mut session_exec = None; let file = File::open(path).unwrap(); for line in io::BufReader::new(file).lines() { let line = line.unwrap(); if line.starts_with("Name=") { session_name = Some(String::from(line.trim_start_matches("Name="))); } else if line.starts_with("Exec=") { session_exec = Some(String::from(line.trim_start_matches("Exec="))); } } if let (Some(name), Some(exec)) = (session_name, session_exec) { Ok(Session { name, exec }) } else { Err(()) } }) .filter_map(|result| result.ok()) .collect(); wayland_sessions } struct Session { name: String, exec: String, } impl ToString for Session { fn to_string(&self) -> String { self.name.clone() } }