summaryrefslogtreecommitdiffstats
path: root/src/opener.rs
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2022-12-07 23:13:13 +0100
committerqkzk <qu3nt1n@gmail.com>2022-12-07 23:13:13 +0100
commit911246b8a80f73d98fd5377554eff2d3acce3e5b (patch)
tree4ca8af1cf88ca624a3cc677c3dbfc2e9a4b5cf80 /src/opener.rs
parent5b6301bc6a38f6fd3fc2b8e33505f9fc3e8407e8 (diff)
opener fallback to xdg-open if opener doesn't exist in path
Diffstat (limited to 'src/opener.rs')
-rw-r--r--src/opener.rs73
1 files changed, 54 insertions, 19 deletions
diff --git a/src/opener.rs b/src/opener.rs
index e42aeef..03f5240 100644
--- a/src/opener.rs
+++ b/src/opener.rs
@@ -1,5 +1,7 @@
use std::collections::HashMap;
+use std::env;
use std::error::Error;
+use std::path::{Path, PathBuf};
use std::process::Command;
use log::info;
@@ -7,7 +9,23 @@ use serde_yaml;
use crate::fm_error::{FmError, FmResult};
-#[derive(Clone, Hash, Eq, PartialEq)]
+fn find_it<P>(exe_name: P) -> Option<PathBuf>
+where
+ P: AsRef<Path>,
+{
+ env::var_os("PATH").and_then(|paths| {
+ env::split_paths(&paths).find_map(|dir| {
+ let full_path = dir.join(&exe_name);
+ if full_path.is_file() {
+ Some(full_path)
+ } else {
+ None
+ }
+ })
+ })
+}
+
+#[derive(Clone, Hash, Eq, PartialEq, Debug)]
pub enum ExtensionKind {
Audio,
Bitmap,
@@ -73,33 +91,44 @@ impl OpenerAssociation {
}
macro_rules! open_file_with {
- ($self:ident, $key:ident, $variant:ident, $yaml:ident) => {
- if let Some($key) = OpenerInfo::from_yaml(&$yaml["$key"]) {
+ ($self:ident, $key:expr, $variant:ident, $yaml:ident) => {
+ if let Some(o) = OpenerInfo::from_yaml(&$yaml[$key]) {
+ info!("key {:?} variant {:?}", $key, ExtensionKind::$variant);
$self
.association
.entry(ExtensionKind::$variant)
- .and_modify(|e| *e = $key);
+ .and_modify(|e| *e = o);
}
};
}
+
impl OpenerAssociation {
fn opener_info(&self, ext: &str) -> Option<&OpenerInfo> {
self.association.get(&ExtensionKind::parse(ext))
}
fn update_from_file(&mut self, yaml: &serde_yaml::value::Value) {
- open_file_with!(self, audio, Audio, yaml);
- open_file_with!(self, bitmap_image, Bitmap, yaml);
- open_file_with!(self, libreoffice, Office, yaml);
- open_file_with!(self, readable, Readable, yaml);
- open_file_with!(self, text, Text, yaml);
- open_file_with!(self, unknown, Unknown, yaml);
- open_file_with!(self, vectorial_image, Vectorial, yaml);
- open_file_with!(self, video, Video, yaml);
+ open_file_with!(self, "audio", Audio, yaml);
+ open_file_with!(self, "bitmap_image", Bitmap, yaml);
+ open_file_with!(self, "libreoffice", Office, yaml);
+ open_file_with!(self, "readable", Readable, yaml);
+ open_file_with!(self, "text", Text, yaml);
+ open_file_with!(self, "unknown", Unknown, yaml);
+ open_file_with!(self, "vectorial_image", Vectorial, yaml);
+ open_file_with!(self, "video", Video, yaml);
+
+ info!("{:?}", self.association);
+
+ self.validate_openers();
+ }
+
+ fn validate_openers(&mut self) {
+ self.association
+ .retain(|_, opener| find_it(opener.opener.clone()).is_some())
}
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct OpenerInfo {
opener: String,
use_term: bool,
@@ -125,6 +154,7 @@ impl OpenerInfo {
pub struct Opener {
terminal: String,
pub opener_association: OpenerAssociation,
+ default_opener: OpenerInfo,
}
impl Opener {
@@ -132,6 +162,15 @@ impl Opener {
Self {
terminal,
opener_association: OpenerAssociation::new(),
+ default_opener: OpenerInfo::new("xdg-open", false),
+ }
+ }
+
+ fn get_opener(&self, extension: &str) -> &OpenerInfo {
+ if let Some(opener) = self.opener_association.opener_info(extension) {
+ opener
+ } else {
+ &self.default_opener
}
}
@@ -147,12 +186,7 @@ impl Opener {
let extension = extension_os_string
.to_str()
.ok_or_else(|| FmError::new("Extension couldn't be parsed correctly"))?;
- self.open_with(
- self.opener_association
- .opener_info(extension)
- .ok_or_else(|| FmError::new("This extension has no known opener"))?,
- filepath,
- )
+ self.open_with(self.get_opener(extension), filepath)
}
pub fn open_with(
@@ -204,6 +238,7 @@ pub fn load_opener(path: &str, terminal: String) -> Result<Opener, Box<dyn Error
let mut opener = Opener::new(terminal);
let file = std::fs::File::open(std::path::Path::new(&shellexpand::tilde(path).to_string()))?;
let yaml = serde_yaml::from_reader(file)?;
+ info!("yaml opener : {:?}", yaml);
opener.update_from_file(&yaml);
Ok(opener)
}