Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: If8fe8b38c1d9c4fecd40ff71f88d2ae06a6a6964
78 lines
1.9 KiB
Rust
78 lines
1.9 KiB
Rust
use std::{path::Path, 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)
|
|
}
|
|
}
|