summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-07-01 17:24:30 +0200
committerrabite <rabite@posteo.de>2019-07-01 17:24:30 +0200
commit366b9c6f3dfd5ce0b7e596f3ad82b3005e8d9759 (patch)
treebb6cb8d8c5f11a71bee7c04697e26f956ff61aa0
parent17abbbd59f17ff43e1c67b94d0175b94ef609436 (diff)
added custom quick action creator based on quick actions
-rwxr-xr-xextra/actions/Add\ Action?type?name!.sh84
-rw-r--r--src/fail.rs23
-rw-r--r--src/main.rs43
-rw-r--r--src/quick_actions.rs16
-rw-r--r--src/trait_ext.rs36
5 files changed, 189 insertions, 13 deletions
diff --git a/extra/actions/Add\ Action?type?name!.sh b/extra/actions/Add\ Action?type?name!.sh
new file mode 100755
index 0000000..6a322bc
--- /dev/null
+++ b/extra/actions/Add\ Action?type?name!.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+
+errecho() {
+ echo ${@} >&2
+}
+
+check_dir() {
+ DIR=${1}
+
+ [ -d ${DIR} ] ||
+ mkdir -p ${DIR} ||
+ (echo "Can't create directory: ${DIR}" && exit 1)
+}
+
+populate_file() {
+ FILE=${1}
+
+ # Don't try to overwrite existing file
+ test -e ${FILE} && return
+
+
+
+ cat > ${FILE} << EOF
+#!/bin/sh
+
+# Selected files are stored here
+FILES=\${@}
+
+# You can interate over them one by one
+for FILE in \${FILES}; do
+ echo \$FILE
+done
+
+# Or process them all at once
+echo "\${FILES}"
+EOF
+}
+
+
+## Starting point
+
+FILE=${1}
+MIME=`hunter -m $FILE`
+STATUS=$?
+
+
+# MIME detection failed, bail out unless type is base
+[ $STATUS != 0 ] && [ $type != "uni" ] &&
+ echo $MIME &&
+ exit 1
+
+# Laziy not using XGD here because of OSX
+ACTDIR="$HOME/.config/hunter/actions/"
+
+MIME_BASE=`echo $MIME | cut -d "/" -f 1`
+MIME_SUB=`echo $MIME | cut -d "/" -f 2`
+
+
+case $type in
+ uni)
+ AFILE="${ACTDIR}/${name}.sh"
+ check_dir "${ACTDIR}"
+ populate_file "${AFILE}"
+ $EDITOR "${AFILE}"
+ test -e "${AFILE}" && chmod +x "${AFILE}"
+ ;;
+ base)
+ BASEDIR="${ACTDIR}/$MIME_BASE"
+ AFILE="${BASEDIR}/${name}.sh"
+ check_dir "${BASEDIR}"
+ populate_file "${AFILE}"
+ $EDITOR "${AFILE}"
+ test -e ${AFILE} && chmod +x "${ACTDIR}/$name"
+ ;;
+ sub)
+ SUBDIR="${ACTDIR}/${MIME_BASE}/${MIME_SUB}"
+ AFILE="${SUBDIR}/${name}.sh"
+ check_dir ${SUBDIR}
+ populate_file "${AFILE}"
+ $EDITOR "${AFILE}"
+ test -e ${AFILE} && chmod+ +x ${AFILE}
+ ;;
+esac
diff --git a/src/fail.rs b/src/fail.rs
index b3351ba..1e6baf0 100644
--- a/src/fail.rs
+++ b/src/fail.rs
@@ -103,7 +103,9 @@ pub enum HError {
#[fail(display = "Failed to parse integer!")]
ParseIntError(std::num::ParseIntError),
#[fail(display = "{}", _0)]
- Media(MediaError)
+ Media(MediaError),
+ #[fail(display = "{}", _0)]
+ Mime(MimeError),
}
impl HError {
@@ -331,3 +333,22 @@ impl From<std::num::ParseIntError> for HError {
err
}
}
+
+
+// MIME Errors
+
+#[derive(Fail, Debug, Clone)]
+pub enum MimeError {
+ #[fail(display = "Need a file to determine MIME type")]
+ NoFileProvided,
+ #[fail(display = "File access failed! Error: {}", _0)]
+ AccessFailed(Box<HError>),
+ #[fail(display = "No MIME type found for this file",)]
+ NoMimeFound
+}
+
+impl From<MimeError> for HError {
+ fn from(e: MimeError) -> Self {
+ HError::Mime(e)
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 57d2dbd..7efbad7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -69,9 +69,10 @@ mod mediaview;
use widget::{Widget, WidgetCore};
use term::ScreenExt;
-use fail::{HResult, HError};
+use fail::{HResult, HError, MimeError};
use file_browser::FileBrowser;
use tabview::TabView;
+use trait_ext::PathBufMime;
fn reset_screen(core: &mut WidgetCore) -> HResult<()> {
@@ -136,8 +137,7 @@ fn parse_args() -> HResult<()> {
.short("a")
.long("animation-off")
.help("Turn off animations")
- .takes_value(false),
- )
+ .takes_value(false))
.arg(
Arg::with_name("show-hidden")
.short("h")
@@ -150,18 +150,32 @@ fn parse_args() -> HResult<()> {
.short("i")
.long("icons")
.help("Show icons for different file types")
- .takes_value(false),
- )
+ .takes_value(false))
+ // For "Add Action" action
+ .arg(
+ Arg::with_name("mime")
+ .short("m")
+ .long("mime")
+ .help("Print MIME type of file")
+ .takes_value(false))
.arg(
Arg::with_name("path")
.index(1)
- .help("Start in <path>")
- )
+ .help("Start in <path>"))
.get_matches();
let path = args.value_of("path");
+ // Just print MIME and quit
+ if args.is_present("mime") {
+ get_mime(path)
+ .map_err(|e| eprintln!("{}", e)).
+ ok();
+ // If we get heres something went wrong.
+ std::process::exit(1)
+ }
+
if let Some(path) = path {
std::env::set_current_dir(&path).ok();
}
@@ -169,3 +183,18 @@ fn parse_args() -> HResult<()> {
crate::config::set_argv_config(args).ok();
Ok(())
}
+
+
+
+
+
+
+fn get_mime(path: Option<&str>) -> HResult<()> {
+ let path = path.ok_or(MimeError::NoFileProvided)?;
+ let path = std::path::PathBuf::from(path);
+ path.get_mime()
+ .map(|mime| println!("{}", mime))
+ .map(|_| std::process::exit(0))
+ .map_err(|e| eprintln!("{}", e))
+ .map_err(|_| std::process::exit(1))
+}
diff --git a/src/quick_actions.rs b/src/quick_actions.rs
index 69bfb78..14c33bc 100644
--- a/src/quick_actions.rs
+++ b/src/quick_actions.rs
@@ -349,17 +349,22 @@ impl QuickAction {
.iter()
.fold(Ok(vec![]), |mut acc, query| {
// If error occured/input was cancelled just skip querying
+ // Turn into try_fold?
if acc.is_err() { return acc; }
match core.minibuffer(query) {
Err(HError::MiniBufferEmptyInput) => {
- acc.as_mut().map(|acc| acc.push((OsString::from(query),
- OsString::from("")))).ok();
+ acc.as_mut()
+ .map(|acc| acc.push((OsString::from(query),
+ OsString::from(""))))
+ .ok();
acc
}
Ok(input) => {
- acc.as_mut().map(|acc| acc.push((OsString::from(query),
- OsString::from(input)))).ok();
+ acc.as_mut()
+ .map(|acc| acc.push((OsString::from(query),
+ OsString::from(input))))
+ .ok();
acc
}
Err(err) => Err(err)
@@ -505,7 +510,8 @@ impl QuickPath for PathBuf {
.collect::<Vec<&str>>()
.iter()
.skip(1)
- .map(|q| q.to_string())
+ // Remove ! in queries from sync actions
+ .map(|q| q.trim_end_matches("!").to_string())
.collect())
.unwrap_or_else(|| vec![])
}
diff --git a/src/trait_ext.rs b/src/trait_ext.rs
index 350138b..51e352e 100644
--- a/src/trait_ext.rs
+++ b/src/trait_ext.rs
@@ -1,3 +1,17 @@
+use std::path::PathBuf;
+
+use crate::fail::{HResult, MimeError};
+use crate::files::File;
+
+
+
+
+
+
+
+
+
+// This makes using short-circuiting iterators more convenient
pub trait ExtractResult<T> {
fn extract(self) -> T;
}
@@ -10,3 +24,25 @@ impl<T> ExtractResult<T> for Result<T,T> {
}
}
}
+
+
+// To get MIME from Path without hassle
+pub trait PathBufMime {
+ fn get_mime(&self) -> HResult<String>;
+}
+
+impl PathBufMime for PathBuf {
+ fn get_mime(&self) -> HResult<String> {
+ let mut file = File::new_from_path(&self, None)
+ .map_err(|e| MimeError::AccessFailed(Box::new(e)))?;
+ file.meta_sync()
+ .map_err(|e| MimeError::AccessFailed(Box::new(e)))?;;
+
+
+ file.get_mime()
+ .map(|mime| {
+ Ok(format!("{}", mime))
+ })
+ .ok_or(MimeError::NoMimeFound)?
+ }
+}