1use crate::config::Config;
2use crate::config::I3Switcher;
3use crate::config::WorkspaceSwitcher;
4use crate::input::Items;
5use anyhow::anyhow;
6use std::io::Write;
7use std::process::Command;
8use std::process::Output;
9use std::process::Stdio;
10
11pub trait ExecSwitcher {
12 fn exec(&self) -> Option<Result<Output, std::io::Error>>;
13}
14
15impl ExecSwitcher for WorkspaceSwitcher {
16 fn exec(&self) -> Option<Result<Output, std::io::Error>> {
17 if let Some(command) = &self.custom {
18 command.exec()
19 } else if let Some(i3_swicth) = &self.i3 {
20 i3_swicth.exec()
21 } else {
22 None
23 }
24 }
25}
26
27impl ExecSwitcher for String {
28 fn exec(&self) -> Option<Result<Output, std::io::Error>> {
29 let values: Vec<String> = self.split(" ").map(|s| s.to_string()).collect();
30 let comm = Command::new(values.first()?)
31 .args(values[1..].iter())
32 .output();
33 Some(comm)
34 }
35}
36
37impl ExecSwitcher for I3Switcher {
38 fn exec(&self) -> Option<Result<Output, std::io::Error>> {
39 Some(
40 Command::new("i3-msg")
41 .args([
42 "workspace",
43 "number",
44 self.workspace_number.to_string().as_str(),
45 ])
46 .output(),
47 )
48 }
49}
50
51pub fn launch_rofi(items: &Items, config: &Config) -> anyhow::Result<Option<String>> {
52 let names = items.get_names();
53
54 let mut child = Command::new("rofi")
55 .args(["-dmenu", "-i", "-theme", config.theme.as_str()])
56 .stdin(Stdio::piped())
57 .stdout(Stdio::piped())
58 .spawn()?;
59
60 let mut stdin = child.stdin.take().ok_or(anyhow!("Cannot open stdin"))?;
61 std::thread::spawn(move || {
62 stdin
63 .write_all(names.as_bytes())
64 .expect("Failed to write to stdin");
65 });
66 let output = child.wait_with_output()?;
67
68 if output.status.success() {
69 let output_string = std::str::from_utf8(&output.stdout)?;
70 if output_string.trim().is_empty() {
71 Err(anyhow!("Empty selection"))
72 } else {
73 Ok(Some(String::from(output_string)))
74 }
75 } else {
76 Ok(None)
77 }
78}
79
80pub fn launch_link(s: &str, items: &Items, config: &Config) -> anyhow::Result<()> {
81 if let Some(switcher) = &config.workspace_switcher {
82 if let Some(output) = switcher.exec() {
83 if !output?.status.success() {
84 return Err(anyhow!("i3-msg failed"));
85 }
86 }
87 }
88
89 let link = items.get_link(s.trim()).ok_or(anyhow!("Invalid item"))?;
90 Command::new(config.browser_command_name.as_str())
91 .args([link])
92 .output()?;
93
94 Ok(())
95}