use std::{io, path::Path, process::Command};
pub fn open(path: &Path) -> io::Result<()> {
if !path.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("file not found: {}", path.display()),
));
}
let status = opener_command(path).status()?;
if status.success() {
Ok(())
} else {
Err(io::Error::other(format!("opener exited with {status}")))
}
}
#[cfg(target_os = "macos")]
fn opener_command(path: &Path) -> Command {
let mut command = Command::new("open");
command.arg(path);
command
}
#[cfg(target_os = "windows")]
fn opener_command(path: &Path) -> Command {
let mut command = Command::new("cmd");
command.args(["/C", "start", ""]).arg(path);
command
}
#[cfg(all(unix, not(target_os = "macos")))]
fn opener_command(path: &Path) -> Command {
let mut command = Command::new("xdg-open");
command.arg(path);
command
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_missing_file_is_reported_as_not_found() {
let error = open(Path::new("/no/such/file/at/all")).unwrap_err();
assert_eq!(error.kind(), io::ErrorKind::NotFound);
}
}