file can now be used as standalone mode
This commit is contained in:
parent
f558131233
commit
d0b526fb9d
7 changed files with 189 additions and 104 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
|
@ -436,6 +436,12 @@ dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
|
@ -1026,9 +1032,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f79496a5651c8d57cd033c5add8ca7ee4e3d5f7587a4777484640d9cb60392d9"
|
checksum = "f79496a5651c8d57cd033c5add8ca7ee4e3d5f7587a4777484640d9cb60392d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"nom",
|
"nom 1.2.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
|
|
@ -1055,6 +1067,16 @@ version = "1.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|
@ -1121,6 +1143,16 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap 2.9.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.11.3"
|
version = "0.11.3"
|
||||||
|
|
@ -1555,6 +1587,19 @@ dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tree_magic_mini"
|
||||||
|
version = "3.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aac5e8971f245c3389a5a76e648bfc80803ae066a1243a75db0064d7c1129d63"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"memchr",
|
||||||
|
"nom 7.1.3",
|
||||||
|
"once_cell",
|
||||||
|
"petgraph",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
|
@ -1755,6 +1800,7 @@ dependencies = [
|
||||||
"strsim 0.11.1",
|
"strsim 0.11.1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
|
"tree_magic_mini",
|
||||||
"which",
|
"which",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,4 @@ strsim = "0.11.1"
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
which = "7.0.3"
|
which = "7.0.3"
|
||||||
meval = "0.2.0"
|
meval = "0.2.0"
|
||||||
|
tree_magic_mini = "3.1.6"
|
||||||
|
|
|
||||||
14
README.md
14
README.md
|
|
@ -1,8 +1,12 @@
|
||||||
# Worf
|
# Worf - Wayland Optimized Run Facilitator
|
||||||
|
|
||||||
|
Worf is yet another style launcher, heavily inspired by wofi, rofi and walker.
|
||||||
|
Worf is written in Rust on top of GTK4.
|
||||||
|
|
||||||
|
It aims to be a drop in replacement for wofi in most part, so it is (almost) compatible with its
|
||||||
|
configuration and css files. See below for differences
|
||||||
|
|
||||||
|
|
||||||
Worf is yet another dmenu style launcher, heavily inspired by wofi but written in Rust on top of GTK4.
|
|
||||||
It supports a lot of things the same way wofi does, so migrating to worf is easy, but things I did not
|
|
||||||
deemed necessary where dropped from worf. See breaking changes section for details.
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|
@ -37,7 +41,7 @@ layerrule = blur, worf
|
||||||
|
|
||||||
## Dropped arguments
|
## Dropped arguments
|
||||||
* `mode`, use show
|
* `mode`, use show
|
||||||
* `D`, arguments are the same as config in worf, no need to have have this flag.
|
* `D`, arguments are the same as config in worf, no need to have this flag.
|
||||||
|
|
||||||
### Dropped configuration options
|
### Dropped configuration options
|
||||||
* stylesheet -> use style instead
|
* stylesheet -> use style instead
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ pub enum Mode {
|
||||||
|
|
||||||
/// tries to determine automatically what to do
|
/// tries to determine automatically what to do
|
||||||
Auto,
|
Auto,
|
||||||
|
|
||||||
|
/// use worf as file browser
|
||||||
|
File,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
@ -80,6 +83,7 @@ impl FromStr for Mode {
|
||||||
"run" => Ok(Mode::Run),
|
"run" => Ok(Mode::Run),
|
||||||
"drun" => Ok(Mode::Drun),
|
"drun" => Ok(Mode::Drun),
|
||||||
"dmenu" => Ok(Mode::Dmenu),
|
"dmenu" => Ok(Mode::Dmenu),
|
||||||
|
"file" => Ok(Mode::File),
|
||||||
"auto" => Ok(Mode::Auto),
|
"auto" => Ok(Mode::Auto),
|
||||||
_ => Err(ArgsError::InvalidParameter(
|
_ => Err(ArgsError::InvalidParameter(
|
||||||
format!("{s} is not a valid argument show this, see help for details").to_owned(),
|
format!("{s} is not a valid argument show this, see help for details").to_owned(),
|
||||||
|
|
@ -128,21 +132,16 @@ pub struct Config {
|
||||||
#[clap(long = "height")]
|
#[clap(long = "height")]
|
||||||
pub height: Option<String>,
|
pub height: Option<String>,
|
||||||
|
|
||||||
|
/// Defines which prompt is used. Default is selected 'show'
|
||||||
#[clap(short = 'p', long = "prompt")]
|
#[clap(short = 'p', long = "prompt")]
|
||||||
pub prompt: Option<String>,
|
pub prompt: Option<String>,
|
||||||
|
|
||||||
#[clap(short = 'x', long = "xoffset")]
|
#[clap(short = 'x', long = "xoffset")]
|
||||||
pub xoffset: Option<i32>,
|
pub xoffset: Option<i32>,
|
||||||
|
|
||||||
#[clap(long = "x")]
|
|
||||||
pub x: Option<i32>,
|
|
||||||
|
|
||||||
#[clap(short = 'y', long = "yoffset")]
|
#[clap(short = 'y', long = "yoffset")]
|
||||||
pub yoffset: Option<i32>,
|
pub yoffset: Option<i32>,
|
||||||
|
|
||||||
#[clap(long = "y")]
|
|
||||||
pub y: Option<i32>,
|
|
||||||
|
|
||||||
/// If true a normal window instead of a layer shell will be used
|
/// If true a normal window instead of a layer shell will be used
|
||||||
#[serde(default = "default_normal_window")]
|
#[serde(default = "default_normal_window")]
|
||||||
#[clap(short = 'n', long = "normal-window")]
|
#[clap(short = 'n', long = "normal-window")]
|
||||||
|
|
@ -315,9 +314,7 @@ impl Default for Config {
|
||||||
height: default_height(),
|
height: default_height(),
|
||||||
prompt: None,
|
prompt: None,
|
||||||
xoffset: None,
|
xoffset: None,
|
||||||
x: None,
|
|
||||||
yoffset: None,
|
yoffset: None,
|
||||||
y: None,
|
|
||||||
normal_window: default_normal_window(),
|
normal_window: default_normal_window(),
|
||||||
allow_images: None,
|
allow_images: None,
|
||||||
allow_markup: None,
|
allow_markup: None,
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ fn build_ui<T, P>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// todo make this configurable
|
/// todo make this configurable
|
||||||
window.set_anchor(Edge::Top, true);
|
//window.set_anchor(Edge::Top, true);
|
||||||
|
|
||||||
let outer_box = gtk4::Box::new(config.orientation.unwrap().into(), 0);
|
let outer_box = gtk4::Box::new(config.orientation.unwrap().into(), 0);
|
||||||
outer_box.set_widget_name("outer-box");
|
outer_box.set_widget_name("outer-box");
|
||||||
|
|
@ -944,7 +944,7 @@ fn percent_or_absolute(value: Option<&String>, base_value: i32) -> Option<i32> {
|
||||||
|
|
||||||
// highly unlikely that we are dealing with > i64 items
|
// highly unlikely that we are dealing with > i64 items
|
||||||
#[allow(clippy::cast_possible_wrap)]
|
#[allow(clippy::cast_possible_wrap)]
|
||||||
pub fn initialize_sort_scores<T: std::clone::Clone>(items: &mut [MenuItem<T>]) {
|
pub fn sort_menu_items_alphabetically_honor_initial_score<T: std::clone::Clone>(items: &mut [MenuItem<T>]) {
|
||||||
let mut regular_score = items.len() as i64;
|
let mut regular_score = items.len() as i64;
|
||||||
items.sort_by(|l, r| l.label.cmp(&r.label));
|
items.sort_by(|l, r| l.label.cmp(&r.label));
|
||||||
|
|
||||||
|
|
|
||||||
208
src/lib/mode.rs
208
src/lib/mode.rs
|
|
@ -124,7 +124,7 @@ impl<T: Clone> DRunProvider<T> {
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
gui::initialize_sort_scores(&mut entries);
|
gui::sort_menu_items_alphabetically_honor_initial_score(&mut entries);
|
||||||
|
|
||||||
DRunProvider {
|
DRunProvider {
|
||||||
items: entries,
|
items: entries,
|
||||||
|
|
@ -134,7 +134,7 @@ impl<T: Clone> DRunProvider<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: std::clone::Clone> ItemProvider<T> for DRunProvider<T> {
|
impl<T: Clone> ItemProvider<T> for DRunProvider<T> {
|
||||||
fn get_elements(&mut self, _: Option<&str>) -> Vec<MenuItem<T>> {
|
fn get_elements(&mut self, _: Option<&str>) -> Vec<MenuItem<T>> {
|
||||||
self.items.clone()
|
self.items.clone()
|
||||||
}
|
}
|
||||||
|
|
@ -144,51 +144,80 @@ impl<T: std::clone::Clone> ItemProvider<T> for DRunProvider<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
enum AutoRunType {
|
|
||||||
Math,
|
|
||||||
DRun,
|
|
||||||
File,
|
|
||||||
Ssh,
|
|
||||||
WebSearch,
|
|
||||||
Emoji,
|
|
||||||
Run,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AutoItemProvider {
|
struct FileItemProvider<T: std::clone::Clone> {
|
||||||
drun_provider: DRunProvider<AutoRunType>,
|
last_result: Option<Vec<MenuItem<T>>>,
|
||||||
last_result: Option<Vec<MenuItem<AutoRunType>>>,
|
menu_item_data: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoItemProvider {
|
impl<T: Clone> FileItemProvider<T> {
|
||||||
fn new() -> Self {
|
fn new(menu_item_data: T) -> Self {
|
||||||
AutoItemProvider {
|
FileItemProvider {
|
||||||
drun_provider: DRunProvider::new(AutoRunType::DRun),
|
|
||||||
|
|
||||||
last_result: None,
|
last_result: None,
|
||||||
|
menu_item_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auto_run_handle_files(&mut self, trimmed_search: &str) -> Vec<MenuItem<AutoRunType>> {
|
fn resolve_icon_for_name(&self, path: PathBuf) -> String {
|
||||||
let folder_icon = "inode-directory";
|
let result = tree_magic_mini::from_filepath(&path);
|
||||||
|
if let Some(result) = result {
|
||||||
|
if result.starts_with("image") {
|
||||||
|
"image-x-generic".to_owned()
|
||||||
|
} else if result.starts_with("inode") {
|
||||||
|
return result.replace("/", "-");
|
||||||
|
} else if result.starts_with("text") {
|
||||||
|
if result.contains("plain") {
|
||||||
|
"text-x-generic".to_owned()
|
||||||
|
} else if result.contains("python") {
|
||||||
|
"text-x-script".to_owned()
|
||||||
|
} else if result.contains("html") {
|
||||||
|
return "text-html".to_owned();
|
||||||
|
} else {
|
||||||
|
"text-x-generic".to_owned()
|
||||||
|
}
|
||||||
|
} else if result.starts_with("application") {
|
||||||
|
if result.contains("octet") {
|
||||||
|
"application-x-executable".to_owned()
|
||||||
|
} else if result.contains("tar")
|
||||||
|
|| result.contains("lz")
|
||||||
|
|| result.contains("zip")
|
||||||
|
|| result.contains("7z")
|
||||||
|
|| result.contains("xz")
|
||||||
|
{
|
||||||
|
"package-x-generic".to_owned()
|
||||||
|
} else {
|
||||||
|
return "text-html".to_owned();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::debug!("unsupported mime type {result}");
|
||||||
|
return "application-x-generic".to_owned();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"image-not-found".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let path = config::expand_path(trimmed_search);
|
impl<T: Clone> ItemProvider<T> for FileItemProvider<T> {
|
||||||
let mut items: Vec<MenuItem<AutoRunType>> = Vec::new();
|
fn get_elements(&mut self, search: Option<&str>) -> Vec<MenuItem<T>> {
|
||||||
|
let default_path = if let Some(home) = dirs::home_dir() {
|
||||||
|
home.display().to_string()
|
||||||
|
} else {
|
||||||
|
"/".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut trimmed_search = search.unwrap_or(&default_path).to_owned();
|
||||||
|
if !trimmed_search.starts_with("/") && !trimmed_search.starts_with("~") {
|
||||||
|
trimmed_search = format!("{default_path}/{trimmed_search}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = expand_path(&trimmed_search);
|
||||||
|
let mut items: Vec<MenuItem<T>> = Vec::new();
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
if let Some(last) = &self.last_result {
|
if let Some(last) = &self.last_result {
|
||||||
if !last.is_empty()
|
|
||||||
&& last.first().is_some_and(|l| {
|
|
||||||
l.as_ref()
|
|
||||||
.data
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|t| t == &AutoRunType::File)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return last.clone();
|
return last.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
@ -210,17 +239,13 @@ impl AutoItemProvider {
|
||||||
items.push({
|
items.push({
|
||||||
MenuItem {
|
MenuItem {
|
||||||
label: path_str.clone(),
|
label: path_str.clone(),
|
||||||
icon_path: if entry.path().is_dir() {
|
icon_path: Some(self.resolve_icon_for_name(entry.path())),
|
||||||
Some(folder_icon.to_owned())
|
|
||||||
} else {
|
|
||||||
Some(resolve_icon_for_name(entry.path()))
|
|
||||||
},
|
|
||||||
action: Some(format!("xdg-open {path_str}")),
|
action: Some(format!("xdg-open {path_str}")),
|
||||||
sub_elements: vec![],
|
sub_elements: vec![],
|
||||||
working_dir: None,
|
working_dir: None,
|
||||||
initial_sort_score: 0,
|
initial_sort_score: 0,
|
||||||
search_sort_score: 0.0,
|
search_sort_score: 0.0,
|
||||||
data: Some(AutoRunType::File),
|
data: Some(self.menu_item_data.clone()),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -229,67 +254,54 @@ impl AutoItemProvider {
|
||||||
items.push({
|
items.push({
|
||||||
MenuItem {
|
MenuItem {
|
||||||
label: trimmed_search.to_owned(),
|
label: trimmed_search.to_owned(),
|
||||||
icon_path: Some(resolve_icon_for_name(PathBuf::from(trimmed_search))),
|
icon_path: Some(self.resolve_icon_for_name(PathBuf::from(&trimmed_search))),
|
||||||
action: Some(format!("xdg-open {trimmed_search}")),
|
action: Some(format!("xdg-open {trimmed_search}")),
|
||||||
sub_elements: vec![],
|
sub_elements: vec![],
|
||||||
working_dir: None,
|
working_dir: None,
|
||||||
initial_sort_score: 0,
|
initial_sort_score: 0,
|
||||||
search_sort_score: 0.0,
|
search_sort_score: 0.0,
|
||||||
data: Some(AutoRunType::File),
|
data: Some(self.menu_item_data.clone()),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gui::sort_menu_items_alphabetically_honor_initial_score(&mut items);
|
||||||
|
|
||||||
self.last_result = Some(items.clone());
|
self.last_result = Some(items.clone());
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sub_elements(&mut self, _: &MenuItem<T>) -> Option<Vec<MenuItem<T>>> {
|
||||||
|
self.last_result.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_icon_for_name(path: PathBuf) -> String {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
// todo use https://docs.rs/tree_magic_mini/latest/tree_magic_mini/ instead
|
enum AutoRunType {
|
||||||
if let Ok(metadata) = fs::symlink_metadata(&path) {
|
Math,
|
||||||
if metadata.file_type().is_symlink() {
|
DRun,
|
||||||
return "inode-symlink".to_owned();
|
File,
|
||||||
} else if metadata.is_dir() {
|
Ssh,
|
||||||
return "inode-directory".to_owned();
|
WebSearch,
|
||||||
} else if metadata.permissions().mode() & 0o111 != 0 {
|
Emoji,
|
||||||
return "application-x-executable".to_owned();
|
Run,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct AutoItemProvider {
|
||||||
|
drun_provider: DRunProvider<AutoRunType>,
|
||||||
|
file_provider: FileItemProvider<AutoRunType>,
|
||||||
|
last_result: Option<Vec<MenuItem<AutoRunType>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AutoItemProvider {
|
||||||
|
fn new() -> Self {
|
||||||
|
AutoItemProvider {
|
||||||
|
drun_provider: DRunProvider::new(AutoRunType::DRun),
|
||||||
|
file_provider: FileItemProvider::new(AutoRunType::File),
|
||||||
|
last_result: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_name = path
|
|
||||||
.file_name()
|
|
||||||
.and_then(|f| f.to_str())
|
|
||||||
.unwrap_or("")
|
|
||||||
.to_lowercase();
|
|
||||||
|
|
||||||
let extension = path
|
|
||||||
.extension()
|
|
||||||
.and_then(|e| e.to_str())
|
|
||||||
.unwrap_or("")
|
|
||||||
.to_lowercase();
|
|
||||||
|
|
||||||
match extension.as_str() {
|
|
||||||
"sh" | "py" | "rb" | "pl" | "bash" => "text-x-script".to_owned(),
|
|
||||||
"c" | "cpp" | "rs" | "java" | "js" | "h" | "hpp" => "text-x-generic".to_owned(),
|
|
||||||
"txt" | "md" | "log" => "text-x-generic".to_owned(),
|
|
||||||
"html" | "htm" => "text-html".to_owned(),
|
|
||||||
"jpg" | "jpeg" | "png" | "gif" | "svg" | "webp" => "image-x-generic".to_owned(),
|
|
||||||
"mp3" | "wav" | "ogg" => "audio-x-generic".to_owned(),
|
|
||||||
"mp4" | "mkv" | "avi" => "video-x-generic".to_owned(),
|
|
||||||
"ttf" | "otf" | "woff" => "font-x-generic".to_owned(),
|
|
||||||
"zip" | "tar" | "gz" | "xz" | "7z" | "lz4" => "package-x-generic".to_owned(),
|
|
||||||
"deb" | "rpm" | "apk" => "x-package-repository".to_owned(),
|
|
||||||
"odt" => "x-office-document".to_owned(),
|
|
||||||
"ott" => "x-office-document-template".to_owned(),
|
|
||||||
"ods" => "x-office-spreadsheet".to_owned(),
|
|
||||||
"ots" => "x-office-spreadsheet-template".to_owned(),
|
|
||||||
"odp" => "x-office-presentation".to_owned(),
|
|
||||||
"otp" => "x-office-presentation-template".to_owned(),
|
|
||||||
"odg" => "x-office-drawing".to_owned(),
|
|
||||||
"vcf" => "x-office-addressbook".to_owned(),
|
|
||||||
_ => "application-x-generic".to_owned(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
||||||
|
|
@ -320,7 +332,7 @@ impl ItemProvider<AutoRunType> for AutoItemProvider {
|
||||||
let item = MenuItem {
|
let item = MenuItem {
|
||||||
label: result,
|
label: result,
|
||||||
icon_path: None,
|
icon_path: None,
|
||||||
action: None,
|
action: Some(trimmed_search.to_owned()),
|
||||||
sub_elements: vec![],
|
sub_elements: vec![],
|
||||||
working_dir: None,
|
working_dir: None,
|
||||||
initial_sort_score: 0,
|
initial_sort_score: 0,
|
||||||
|
|
@ -333,7 +345,7 @@ impl ItemProvider<AutoRunType> for AutoItemProvider {
|
||||||
|| trimmed_search.starts_with("/")
|
|| trimmed_search.starts_with("/")
|
||||||
|| trimmed_search.starts_with("~")
|
|| trimmed_search.starts_with("~")
|
||||||
{
|
{
|
||||||
self.auto_run_handle_files(trimmed_search)
|
self.file_provider.get_elements(search_opt)
|
||||||
} else {
|
} else {
|
||||||
return self.drun_provider.get_elements(search_opt);
|
return self.drun_provider.get_elements(search_opt);
|
||||||
}
|
}
|
||||||
|
|
@ -414,6 +426,28 @@ pub fn auto(config: &mut Config) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file(config: &mut Config) -> Result<(), String> {
|
||||||
|
let provider = FileItemProvider::new("".to_owned());
|
||||||
|
if config.prompt.is_none() {
|
||||||
|
config.prompt = Some("file".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo ues a arc instead of cloning the config
|
||||||
|
let selection_result = gui::show(config.clone(), provider);
|
||||||
|
match selection_result {
|
||||||
|
Ok(s) => {
|
||||||
|
if let Some(action) = s.action {
|
||||||
|
spawn_fork(&action, s.working_dir.as_ref()).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
log::error!("No item selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn update_drun_cache_and_run<T: Clone>(
|
fn update_drun_cache_and_run<T: Clone>(
|
||||||
cache_path: Option<PathBuf>,
|
cache_path: Option<PathBuf>,
|
||||||
cache: &mut HashMap<String, i64>,
|
cache: &mut HashMap<String, i64>,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ fn main() -> anyhow::Result<()> {
|
||||||
Mode::Dmenu => {
|
Mode::Dmenu => {
|
||||||
todo!("dmenu not implemented")
|
todo!("dmenu not implemented")
|
||||||
}
|
}
|
||||||
|
Mode::File => {
|
||||||
|
mode::file(&mut config).map_err(|e| anyhow!(e))?;
|
||||||
|
}
|
||||||
Mode::Auto => {
|
Mode::Auto => {
|
||||||
mode::auto(&mut config)?;
|
mode::auto(&mut config)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue