1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::{
ffi::OsStr,
io,
process::{Command, Child, ExitStatus},
};
pub const OPEN_TOOL: &str = {
cfg_if! {
if #[cfg(target_os = "macos")] {
let open = "/usr/bin/open";
} else if #[cfg(target_os = "linux")] {
let open = "xdg-open";
} else if #[cfg(target_os = "windows")] {
let open = "start";
} else {
compile_error!(
"No known way of opening a resource on the current platform."
);
}
};
open
};
pub fn open<R>(resources: &[R]) -> io::Result<()>
where R: AsRef<OsStr>
{
fn status_to_result(status: ExitStatus) -> io::Result<()> {
if status.success() {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::Other,
format!("Opening finished with status {}", status),
))
}
}
if resources.is_empty() {
return Ok(());
}
if cfg!(target_os = "macos") {
let mut cmd = Command::new(OPEN_TOOL);
cmd.args(resources);
status_to_result(cmd.status()?)
} else {
let children: Vec::<io::Result<Child>> = resources
.iter()
.map(|res| {
let mut cmd = Command::new(OPEN_TOOL);
cmd.arg(res);
cmd.spawn()
})
.collect();
for child in children {
status_to_result(child?.wait()?)?;
}
Ok(())
}
}