Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I4a6b498153eccd5407510dd541b7f4816a6a6964
79 lines
2.1 KiB
Rust
79 lines
2.1 KiB
Rust
use std::path::Path;
|
|
use std::process::Command;
|
|
|
|
use crate::error::{PinakesError, Result};
|
|
|
|
pub trait Opener: Send + Sync {
|
|
fn open(&self, path: &Path) -> Result<()>;
|
|
}
|
|
|
|
/// Linux opener using xdg-open
|
|
pub struct XdgOpener;
|
|
|
|
impl Opener for XdgOpener {
|
|
fn open(&self, path: &Path) -> Result<()> {
|
|
let status = Command::new("xdg-open")
|
|
.arg(path)
|
|
.status()
|
|
.map_err(|e| PinakesError::InvalidOperation(format!("failed to run xdg-open: {e}")))?;
|
|
if status.success() {
|
|
Ok(())
|
|
} else {
|
|
Err(PinakesError::InvalidOperation(format!(
|
|
"xdg-open exited with status {status}"
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// macOS opener using the `open` command
|
|
pub struct MacOpener;
|
|
|
|
impl Opener for MacOpener {
|
|
fn open(&self, path: &Path) -> Result<()> {
|
|
let status = Command::new("open")
|
|
.arg(path)
|
|
.status()
|
|
.map_err(|e| PinakesError::InvalidOperation(format!("failed to run open: {e}")))?;
|
|
if status.success() {
|
|
Ok(())
|
|
} else {
|
|
Err(PinakesError::InvalidOperation(format!(
|
|
"open exited with status {status}"
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Windows opener using `cmd /c start`
|
|
pub struct WindowsOpener;
|
|
|
|
impl Opener for WindowsOpener {
|
|
fn open(&self, path: &Path) -> Result<()> {
|
|
let status = Command::new("cmd")
|
|
.args(["/C", "start", ""])
|
|
.arg(path)
|
|
.status()
|
|
.map_err(|e| {
|
|
PinakesError::InvalidOperation(format!("failed to run cmd /c start: {e}"))
|
|
})?;
|
|
if status.success() {
|
|
Ok(())
|
|
} else {
|
|
Err(PinakesError::InvalidOperation(format!(
|
|
"cmd /c start exited with status {status}"
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Returns the platform-appropriate opener.
|
|
pub fn default_opener() -> Box<dyn Opener> {
|
|
if cfg!(target_os = "macos") {
|
|
Box::new(MacOpener)
|
|
} else if cfg!(target_os = "windows") {
|
|
Box::new(WindowsOpener)
|
|
} else {
|
|
Box::new(XdgOpener)
|
|
}
|
|
}
|