parent
172d9dc589
commit
f10e9d1794
11 changed files with 65 additions and 52 deletions
|
@ -2,17 +2,15 @@ use std::{
|
||||||
env,
|
env,
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, LazyLock, Mutex, RwLock},
|
||||||
thread::sleep,
|
thread::sleep,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use hyprland::data::Client;
|
|
||||||
use hyprland::dispatch::WindowIdentifier;
|
|
||||||
use hyprland::{
|
use hyprland::{
|
||||||
data::{Workspace, Workspaces},
|
data::{Client, Workspace, Workspaces},
|
||||||
dispatch::{Dispatch, DispatchType, WorkspaceIdentifierWithSpecial},
|
dispatch::{Dispatch, DispatchType, WindowIdentifier, WorkspaceIdentifierWithSpecial},
|
||||||
prelude::HyprData,
|
prelude::HyprData,
|
||||||
shared::HyprDataActive,
|
shared::HyprDataActive,
|
||||||
};
|
};
|
||||||
|
@ -478,12 +476,14 @@ fn main() -> Result<(), String> {
|
||||||
cfg.worf.set_prompt(cfg.hypr_space_mode().to_string());
|
cfg.worf.set_prompt(cfg.hypr_space_mode().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let pattern = Mode::iter()
|
static PATTERN_RE: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
.map(|m| regex::escape(&m.to_string().to_lowercase()))
|
let pattern = Mode::iter()
|
||||||
.collect::<Vec<_>>()
|
.map(|m| regex::escape(&m.to_string().to_lowercase()))
|
||||||
.join("|");
|
.collect::<Vec<_>>()
|
||||||
|
.join("|");
|
||||||
let pattern = Regex::new(&format!("(?i){pattern}")).map_err(|e| e.to_string())?;
|
Regex::new(&format!("(?i){pattern}")).unwrap()
|
||||||
|
});
|
||||||
|
let pattern = PATTERN_RE.clone();
|
||||||
|
|
||||||
let provider = Arc::new(Mutex::new(HyprspaceProvider::new(
|
let provider = Arc::new(Mutex::new(HyprspaceProvider::new(
|
||||||
&cfg,
|
&cfg,
|
||||||
|
|
|
@ -6,9 +6,11 @@ use std::{
|
||||||
os::unix::{fs::PermissionsExt, prelude::CommandExt},
|
os::unix::{fs::PermissionsExt, prelude::CommandExt},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
|
sync::LazyLock,
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// re-export freedesktop_file_parser for easier access
|
||||||
pub use freedesktop_file_parser::{DesktopFile, EntryType};
|
pub use freedesktop_file_parser::{DesktopFile, EntryType};
|
||||||
use notify_rust::Notification;
|
use notify_rust::Notification;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
@ -26,8 +28,9 @@ use crate::{
|
||||||
/// When it cannot parse the internal regex
|
/// When it cannot parse the internal regex
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn known_image_extension_regex_pattern() -> Regex {
|
pub fn known_image_extension_regex_pattern() -> Regex {
|
||||||
Regex::new(r"(?i).*\.(png|jpg|gif|svg|jpeg)$")
|
static RE: LazyLock<Regex> =
|
||||||
.expect("Internal image regex is not valid anymore.")
|
LazyLock::new(|| Regex::new(r"(?i).*\.(png|jpg|gif|svg|jpeg)$").unwrap());
|
||||||
|
RE.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to retrieve a file with given regex.
|
/// Helper function to retrieve a file with given regex.
|
||||||
|
@ -59,6 +62,8 @@ fn find_files(folder: &Path, file_name: &Regex) -> Option<Vec<PathBuf>> {
|
||||||
/// When it cannot parse the internal regex
|
/// When it cannot parse the internal regex
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn find_desktop_files() -> Vec<DesktopFile> {
|
pub fn find_desktop_files() -> Vec<DesktopFile> {
|
||||||
|
static DESKTOP_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?i).*\.desktop$").unwrap());
|
||||||
|
|
||||||
let mut paths = vec![
|
let mut paths = vec![
|
||||||
PathBuf::from("/usr/share/applications"),
|
PathBuf::from("/usr/share/applications"),
|
||||||
PathBuf::from("/usr/local/share/applications"),
|
PathBuf::from("/usr/local/share/applications"),
|
||||||
|
@ -81,12 +86,10 @@ pub fn find_desktop_files() -> Vec<DesktopFile> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let regex = &Regex::new("(?i).*\\.desktop$").expect("invalid internal regex");
|
|
||||||
|
|
||||||
let p: Vec<_> = paths
|
let p: Vec<_> = paths
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.filter(|desktop_dir| desktop_dir.exists())
|
.filter(|desktop_dir| desktop_dir.exists())
|
||||||
.filter_map(|desktop_dir| find_files(&desktop_dir, regex))
|
.filter_map(|desktop_dir| find_files(&desktop_dir, &DESKTOP_RE))
|
||||||
.flat_map(|desktop_files| {
|
.flat_map(|desktop_files| {
|
||||||
desktop_files.into_par_iter().filter_map(|desktop_file| {
|
desktop_files.into_par_iter().filter_map(|desktop_file| {
|
||||||
fs::read_to_string(desktop_file)
|
fs::read_to_string(desktop_file)
|
||||||
|
@ -160,7 +163,9 @@ pub fn fork_if_configured(config: &Config) {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// When internal regex unwrapping fails. Should not happen as the regex is static
|
/// When internal regex unwrapping fails. Should not happen as the regex is static
|
||||||
pub fn spawn_fork(cmd: &str, working_dir: Option<&String>) -> Result<(), Error> {
|
pub fn spawn_fork(cmd: &str, working_dir: Option<&String>) -> Result<(), Error> {
|
||||||
let re = Regex::new(r#"'([^']*)'|"([^"]*)"|(\S+)"#).expect("invalid regex in spawn_fork");
|
static RE: LazyLock<Regex> =
|
||||||
|
LazyLock::new(|| Regex::new(r#"'([^']*)'|"([^"]*)"|(\S+)"#).unwrap());
|
||||||
|
let re = &*RE;
|
||||||
let parts: Vec<String> = re
|
let parts: Vec<String> = re
|
||||||
.captures_iter(cmd)
|
.captures_iter(cmd)
|
||||||
.map(|cap| {
|
.map(|cap| {
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use regex::Regex;
|
use std::sync::{Arc, LazyLock, Mutex, RwLock};
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::gui::ArcProvider;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
config::Config,
|
config::Config,
|
||||||
desktop::spawn_fork,
|
desktop::spawn_fork,
|
||||||
gui::{self, DefaultItemFactory, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
gui::{
|
||||||
|
self, ArcProvider, DefaultItemFactory, ExpandMode, ItemProvider, MenuItem, ProviderData,
|
||||||
|
},
|
||||||
modes::{
|
modes::{
|
||||||
drun::{DRunProvider, update_drun_cache_and_run},
|
drun::{DRunProvider, update_drun_cache_and_run},
|
||||||
file::FileItemProvider,
|
file::FileItemProvider,
|
||||||
|
@ -74,15 +76,15 @@ impl AutoItemProvider {
|
||||||
|
|
||||||
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
||||||
// Regex for function names (word boundaries to match whole words)
|
// Regex for function names (word boundaries to match whole words)
|
||||||
let math_functions = r"\b(sqrt|abs|exp|ln|sin|cos|tan|asin|acos|atan|atan2|sinh|cosh|tanh|asinh|acosh|atanh|floor|ceil|round|signum|min|max|pi|e|0x|0b|\||&|<<|>>|\^)\b";
|
static MATH_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
|
Regex::new(r"\b(sqrt|abs|exp|ln|sin|cos|tan|asin|acos|atan|atan2|sinh|cosh|tanh|asinh|acosh|atanh|floor|ceil|round|signum|min|max|pi|e|0x|0b|\||&|<<|>>|\^)\b").unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
// Regex for strings that start with a number (including decimals)
|
// Regex for strings that start with a number (including decimals)
|
||||||
let starts_with_number = r"^\s*[+-]?(\d+(\.\d*)?|\.\d+)";
|
static NUMBER_REGEX: LazyLock<Regex> =
|
||||||
|
LazyLock::new(|| Regex::new(r"^\s*[+-]?(\d+(\.\d*)?|\.\d+)").unwrap());
|
||||||
|
|
||||||
let math_regex = Regex::new(math_functions).unwrap();
|
MATH_REGEX.is_match(input) || NUMBER_REGEX.is_match(input)
|
||||||
let number_regex = Regex::new(starts_with_number).unwrap();
|
|
||||||
|
|
||||||
math_regex.is_match(input) || number_regex.is_match(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemProvider<AutoRunType> for AutoItemProvider {
|
impl ItemProvider<AutoRunType> for AutoItemProvider {
|
||||||
|
@ -99,7 +101,8 @@ impl ItemProvider<AutoRunType> for AutoItemProvider {
|
||||||
} else if search.starts_with("ssh") {
|
} else if search.starts_with("ssh") {
|
||||||
(AutoRunType::Ssh, self.ssh.get_elements(search_opt))
|
(AutoRunType::Ssh, self.ssh.get_elements(search_opt))
|
||||||
} else if search.starts_with('?') {
|
} else if search.starts_with('?') {
|
||||||
let re = Regex::new(r"^\?\s*").unwrap();
|
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^\?\s*").unwrap());
|
||||||
|
let re = &*RE;
|
||||||
let query = re.replace(search, "");
|
let query = re.replace(search, "");
|
||||||
(
|
(
|
||||||
AutoRunType::WebSearch,
|
AutoRunType::WebSearch,
|
||||||
|
@ -151,7 +154,7 @@ pub fn show(config: &Arc<RwLock<Config>>) -> Result<(), Error> {
|
||||||
Some(
|
Some(
|
||||||
vec!["ssh", "emoji", "^\\$\\w+", "^\\?\\s*"]
|
vec!["ssh", "emoji", "^\\$\\w+", "^\\?\\s*"]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| Regex::new(s).unwrap())
|
.map(|s| Regex::new(s).unwrap()) // Consider precompiling if s is constant
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
ExpandMode::Verbatim,
|
ExpandMode::Verbatim,
|
||||||
|
|
|
@ -9,7 +9,6 @@ use freedesktop_file_parser::EntryType;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::gui::ArcProvider;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
config::{Config, SortOrder},
|
config::{Config, SortOrder},
|
||||||
|
@ -17,7 +16,7 @@ use crate::{
|
||||||
find_desktop_files, get_locale_variants, lookup_name_with_locale, save_cache_file,
|
find_desktop_files, get_locale_variants, lookup_name_with_locale, save_cache_file,
|
||||||
spawn_fork,
|
spawn_fork,
|
||||||
},
|
},
|
||||||
gui::{self, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
gui::{self, ArcProvider, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
||||||
modes::load_cache,
|
modes::load_cache,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use regex::Regex;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
os::unix::fs::FileTypeExt,
|
os::unix::fs::FileTypeExt,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, LazyLock, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
config::{Config, SortOrder, expand_path},
|
config::{Config, SortOrder, expand_path},
|
||||||
|
@ -201,6 +201,8 @@ impl<T: Clone> ItemProvider<T> for FileItemProvider<T> {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// In case an internal regex does not parse anymore, this should never happen
|
/// In case an internal regex does not parse anymore, this should never happen
|
||||||
pub fn show(config: &Arc<RwLock<Config>>) -> Result<(), Error> {
|
pub fn show(config: &Arc<RwLock<Config>>) -> Result<(), Error> {
|
||||||
|
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^\$\w+").unwrap());
|
||||||
|
|
||||||
let provider = Arc::new(Mutex::new(FileItemProvider::new(
|
let provider = Arc::new(Mutex::new(FileItemProvider::new(
|
||||||
0,
|
0,
|
||||||
config.read().unwrap().sort_order(),
|
config.read().unwrap().sort_order(),
|
||||||
|
@ -211,7 +213,7 @@ pub fn show(config: &Arc<RwLock<Config>>) -> Result<(), Error> {
|
||||||
config,
|
config,
|
||||||
provider,
|
provider,
|
||||||
None,
|
None,
|
||||||
Some(vec![Regex::new("^\\$\\w+").unwrap()]),
|
Some(vec![RE.clone()]),
|
||||||
ExpandMode::Verbatim,
|
ExpandMode::Verbatim,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, LazyLock, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -79,13 +79,12 @@ enum Value {
|
||||||
|
|
||||||
/// Normalize base literals like 0x and 0b into decimal format
|
/// Normalize base literals like 0x and 0b into decimal format
|
||||||
fn normalize_bases(expr: &str) -> String {
|
fn normalize_bases(expr: &str) -> String {
|
||||||
let hex_re = Regex::new(r"0x[0-9a-fA-F]+").unwrap();
|
static HEX_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"0x[0-9a-fA-F]+").unwrap());
|
||||||
let expr = hex_re.replace_all(expr, |caps: ®ex::Captures| {
|
static BIN_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"0b[01]+").unwrap());
|
||||||
|
let expr = HEX_RE.replace_all(expr, |caps: ®ex::Captures| {
|
||||||
i64::from_str_radix(&caps[0][2..], 16).unwrap().to_string()
|
i64::from_str_radix(&caps[0][2..], 16).unwrap().to_string()
|
||||||
});
|
});
|
||||||
|
BIN_RE
|
||||||
let bin_re = Regex::new(r"0b[01]+").unwrap();
|
|
||||||
bin_re
|
|
||||||
.replace_all(&expr, |caps: ®ex::Captures| {
|
.replace_all(&expr, |caps: ®ex::Captures| {
|
||||||
i64::from_str_radix(&caps[0][2..], 2).unwrap().to_string()
|
i64::from_str_radix(&caps[0][2..], 2).unwrap().to_string()
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,12 +7,11 @@ use std::{
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::gui::ArcProvider;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
config::{Config, SortOrder},
|
config::{Config, SortOrder},
|
||||||
desktop::{is_executable, save_cache_file},
|
desktop::{is_executable, save_cache_file},
|
||||||
gui::{self, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
gui::{self, ArcProvider, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
||||||
modes::load_cache,
|
modes::load_cache,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
use urlencoding::encode;
|
use urlencoding::encode;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use regex::Regex;
|
use std::{
|
||||||
use std::fs;
|
fs,
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
sync::{Arc, LazyLock, Mutex, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::gui::{ExpandMode, ProviderData};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
config::{Config, SortOrder},
|
config::{Config, SortOrder},
|
||||||
desktop::spawn_fork,
|
desktop::spawn_fork,
|
||||||
gui::{self, ItemProvider, MenuItem},
|
gui::{self, ExpandMode, ItemProvider, MenuItem, ProviderData},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -17,7 +19,8 @@ pub(crate) struct SshProvider<T: Clone> {
|
||||||
|
|
||||||
impl<T: Clone> SshProvider<T> {
|
impl<T: Clone> SshProvider<T> {
|
||||||
pub(crate) fn new(menu_item_data: T, order: &SortOrder) -> Self {
|
pub(crate) fn new(menu_item_data: T, order: &SortOrder) -> Self {
|
||||||
let re = Regex::new(r"(?m)^\s*Host\s+(.+)$").unwrap();
|
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?m)^\s*Host\s+(.+)$").unwrap());
|
||||||
|
let re = &*RE;
|
||||||
let mut items: Vec<_> = dirs::home_dir()
|
let mut items: Vec<_> = dirs::home_dir()
|
||||||
.map(|home| home.join(".ssh").join("config"))
|
.map(|home| home.join(".ssh").join("config"))
|
||||||
.filter(|path| path.exists())
|
.filter(|path| path.exists())
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use clap::Parser;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
fmt::Display,
|
||||||
|
str::FromStr,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
use worf::{Error, config, desktop::fork_if_configured, modes};
|
use worf::{Error, config, desktop::fork_if_configured, modes};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Configuration and command line parsing
|
/// Configuration and command line parsing
|
||||||
|
|
Loading…
Add table
Reference in a new issue