pinakes/crates/pinakes-core/src/opener.rs
NotAShelf 3ccddce7fd
treewide: fix various UI bugs; optimize crypto dependencies & format
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: If8fe8b38c1d9c4fecd40ff71f88d2ae06a6a6964
2026-03-06 18:29:33 +03:00

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)
}
}