add math as own mode
This commit is contained in:
parent
d0b526fb9d
commit
d08893d545
3 changed files with 93 additions and 121 deletions
|
|
@ -67,6 +67,9 @@ pub enum Mode {
|
||||||
|
|
||||||
/// use worf as file browser
|
/// use worf as file browser
|
||||||
File,
|
File,
|
||||||
|
|
||||||
|
/// Use is as calculator
|
||||||
|
Math,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
@ -84,6 +87,7 @@ impl FromStr for Mode {
|
||||||
"drun" => Ok(Mode::Drun),
|
"drun" => Ok(Mode::Drun),
|
||||||
"dmenu" => Ok(Mode::Dmenu),
|
"dmenu" => Ok(Mode::Dmenu),
|
||||||
"file" => Ok(Mode::File),
|
"file" => Ok(Mode::File),
|
||||||
|
"math" => Ok(Mode::Math),
|
||||||
"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(),
|
||||||
|
|
|
||||||
126
src/lib/mode.rs
126
src/lib/mode.rs
|
|
@ -24,7 +24,7 @@ struct DRunCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct DRunProvider<T: std::clone::Clone> {
|
struct DRunProvider<T: Clone> {
|
||||||
items: Vec<MenuItem<T>>,
|
items: Vec<MenuItem<T>>,
|
||||||
cache_path: Option<PathBuf>,
|
cache_path: Option<PathBuf>,
|
||||||
cache: HashMap<String, i64>,
|
cache: HashMap<String, i64>,
|
||||||
|
|
@ -145,7 +145,7 @@ impl<T: Clone> ItemProvider<T> for DRunProvider<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct FileItemProvider<T: std::clone::Clone> {
|
struct FileItemProvider<T: Clone> {
|
||||||
last_result: Option<Vec<MenuItem<T>>>,
|
last_result: Option<Vec<MenuItem<T>>>,
|
||||||
menu_item_data: T,
|
menu_item_data: T,
|
||||||
}
|
}
|
||||||
|
|
@ -276,22 +276,78 @@ impl<T: Clone> ItemProvider<T> for FileItemProvider<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct MathProvider<T: Clone> {
|
||||||
|
menu_item_data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::clone::Clone> MathProvider<T> {
|
||||||
|
fn new(menu_item_data: T) -> Self {
|
||||||
|
Self {
|
||||||
|
menu_item_data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
||||||
|
// 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)\b";
|
||||||
|
|
||||||
|
// Regex for strings that start with a number (including decimals)
|
||||||
|
let starts_with_number = r"^\s*[+-]?(\d+(\.\d*)?|\.\d+)";
|
||||||
|
|
||||||
|
let math_regex = Regex::new(math_functions).unwrap();
|
||||||
|
let number_regex = Regex::new(starts_with_number).unwrap();
|
||||||
|
|
||||||
|
math_regex.is_match(input) || number_regex.is_match(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> ItemProvider<T> for MathProvider<T> {
|
||||||
|
fn get_elements(&mut self, search: Option<&str>) -> Vec<MenuItem<T>> {
|
||||||
|
if let Some(search_text) = search {
|
||||||
|
let result = match meval::eval_str(search_text) {
|
||||||
|
Ok(result) => result.to_string(),
|
||||||
|
Err(e) => format!("failed to calculate {e:?}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let item = MenuItem {
|
||||||
|
label: result,
|
||||||
|
icon_path: None,
|
||||||
|
action: search.map(|s| s.to_string()),
|
||||||
|
sub_elements: vec![],
|
||||||
|
working_dir: None,
|
||||||
|
initial_sort_score: 0,
|
||||||
|
search_sort_score: 0.0,
|
||||||
|
data: Some(self.menu_item_data.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![item]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_sub_elements(&mut self, item: &MenuItem<T>) -> Option<Vec<MenuItem<T>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
enum AutoRunType {
|
enum AutoRunType {
|
||||||
Math,
|
Math,
|
||||||
DRun,
|
DRun,
|
||||||
File,
|
File,
|
||||||
Ssh,
|
// Ssh,
|
||||||
WebSearch,
|
// WebSearch,
|
||||||
Emoji,
|
// Emoji,
|
||||||
Run,
|
// Run,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AutoItemProvider {
|
struct AutoItemProvider {
|
||||||
drun_provider: DRunProvider<AutoRunType>,
|
drun_provider: DRunProvider<AutoRunType>,
|
||||||
file_provider: FileItemProvider<AutoRunType>,
|
file_provider: FileItemProvider<AutoRunType>,
|
||||||
last_result: Option<Vec<MenuItem<AutoRunType>>>,
|
math_provider: MathProvider<AutoRunType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoItemProvider {
|
impl AutoItemProvider {
|
||||||
|
|
@ -299,55 +355,26 @@ impl AutoItemProvider {
|
||||||
AutoItemProvider {
|
AutoItemProvider {
|
||||||
drun_provider: DRunProvider::new(AutoRunType::DRun),
|
drun_provider: DRunProvider::new(AutoRunType::DRun),
|
||||||
file_provider: FileItemProvider::new(AutoRunType::File),
|
file_provider: FileItemProvider::new(AutoRunType::File),
|
||||||
last_result: None,
|
math_provider: MathProvider::new(AutoRunType::Math),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
|
||||||
// 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)\b";
|
|
||||||
|
|
||||||
// Regex for strings that start with a number (including decimals)
|
|
||||||
let starts_with_number = r"^\s*[+-]?(\d+(\.\d*)?|\.\d+)";
|
|
||||||
|
|
||||||
let math_regex = Regex::new(math_functions).unwrap();
|
|
||||||
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 {
|
||||||
fn get_elements(&mut self, search_opt: Option<&str>) -> Vec<MenuItem<AutoRunType>> {
|
fn get_elements(&mut self, search_opt: Option<&str>) -> Vec<MenuItem<AutoRunType>> {
|
||||||
if let Some(search) = search_opt {
|
if let Some(search) = search_opt {
|
||||||
let trimmed_search = search.trim();
|
let trimmed_search = search.trim();
|
||||||
if trimmed_search.is_empty() {
|
if trimmed_search.is_empty() {
|
||||||
self.drun_provider.get_elements(search_opt)
|
self.drun_provider.get_elements(search_opt)
|
||||||
} else if contains_math_functions_or_starts_with_number(trimmed_search) {
|
} else if MathProvider::<AutoRunType>::contains_math_functions_or_starts_with_number(trimmed_search) {
|
||||||
let result = match meval::eval_str(trimmed_search) {
|
self.math_provider.get_elements(search_opt)
|
||||||
Ok(result) => result.to_string(),
|
|
||||||
Err(e) => format!("failed to calculate {e:?}"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let item = MenuItem {
|
|
||||||
label: result,
|
|
||||||
icon_path: None,
|
|
||||||
action: Some(trimmed_search.to_owned()),
|
|
||||||
sub_elements: vec![],
|
|
||||||
working_dir: None,
|
|
||||||
initial_sort_score: 0,
|
|
||||||
search_sort_score: 0.0,
|
|
||||||
data: Some(AutoRunType::Math),
|
|
||||||
};
|
|
||||||
|
|
||||||
return vec![item];
|
|
||||||
} else if trimmed_search.starts_with("$")
|
} else if trimmed_search.starts_with("$")
|
||||||
|| trimmed_search.starts_with("/")
|
|| trimmed_search.starts_with("/")
|
||||||
|| trimmed_search.starts_with("~")
|
|| trimmed_search.starts_with("~")
|
||||||
{
|
{
|
||||||
self.file_provider.get_elements(search_opt)
|
self.file_provider.get_elements(search_opt)
|
||||||
} else {
|
} else {
|
||||||
return self.drun_provider.get_elements(search_opt);
|
self.drun_provider.get_elements(search_opt)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.drun_provider.get_elements(search_opt)
|
self.drun_provider.get_elements(search_opt)
|
||||||
|
|
@ -448,6 +475,25 @@ pub fn file(config: &mut Config) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn math(config: &mut Config) -> Result<(), String> {
|
||||||
|
let provider = MathProvider::new("".to_owned());
|
||||||
|
if config.prompt.is_none() {
|
||||||
|
config.prompt = Some("math".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo ues a arc instead of cloning the config
|
||||||
|
let selection_result = gui::show(config.clone(), provider);
|
||||||
|
match selection_result {
|
||||||
|
Ok(_) => {
|
||||||
|
}
|
||||||
|
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>,
|
||||||
|
|
|
||||||
84
src/main.rs
84
src/main.rs
|
|
@ -29,6 +29,9 @@ fn main() -> anyhow::Result<()> {
|
||||||
Mode::File => {
|
Mode::File => {
|
||||||
mode::file(&mut config).map_err(|e| anyhow!(e))?;
|
mode::file(&mut config).map_err(|e| anyhow!(e))?;
|
||||||
}
|
}
|
||||||
|
Mode::Math => {
|
||||||
|
mode::math(&mut config).map_err(|e| anyhow!(e))?;
|
||||||
|
}
|
||||||
Mode::Auto => {
|
Mode::Auto => {
|
||||||
mode::auto(&mut config)?;
|
mode::auto(&mut config)?;
|
||||||
}
|
}
|
||||||
|
|
@ -39,84 +42,3 @@ fn main() -> anyhow::Result<()> {
|
||||||
Err(anyhow!("No mode provided"))
|
Err(anyhow!("No mode provided"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// fn main() -> anyhow::Result<()> {
|
|
||||||
// env_logger::Builder::new()
|
|
||||||
// // todo change to info as default
|
|
||||||
// .parse_filters(&std::env::var("RUST_LOG").unwrap_or_else(|_| "debug".to_owned()))
|
|
||||||
// .init();
|
|
||||||
// let args = Args::parse();
|
|
||||||
//
|
|
||||||
// let home_dir = std::env::var("HOME")?;
|
|
||||||
// let config_path = args.config.as_ref().map(|c| PathBuf::from(c)).unwrap_or_else(||{
|
|
||||||
// std::env::var("XDG_CONF_HOME")
|
|
||||||
// .map_or(
|
|
||||||
// PathBuf::from(home_dir.clone()).join(".config"),
|
|
||||||
// |xdg_conf_home| PathBuf::from(&xdg_conf_home),
|
|
||||||
// )
|
|
||||||
// .join("wofi")// todo change to ravi
|
|
||||||
// .join("config")
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// let colors_dir = std::env::var("XDG_CACHE_HOME")
|
|
||||||
// .map_or(
|
|
||||||
// PathBuf::from(home_dir.clone()).join(".cache"),
|
|
||||||
// |xdg_conf_home| PathBuf::from(&xdg_conf_home),
|
|
||||||
// )
|
|
||||||
// .join("wal")
|
|
||||||
// .join("colors");
|
|
||||||
//
|
|
||||||
// let toml_content = fs::read_to_string(config_path)?;
|
|
||||||
// let config: Config = toml::from_str(&toml_content).unwrap_or_default();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// gtk4::init()?;
|
|
||||||
//
|
|
||||||
// let application = Application::builder()
|
|
||||||
// .application_id("com.example.FirstGtkApp")
|
|
||||||
// .build();
|
|
||||||
//
|
|
||||||
// application.connect_activate(|app| {
|
|
||||||
// let window = ApplicationWindow::builder()
|
|
||||||
// .application(app)
|
|
||||||
// .title("First GTK Program")
|
|
||||||
// .name("window")
|
|
||||||
// .default_width(config.x.clone().unwrap())
|
|
||||||
// .default_height(config.y.clone().unwrap())
|
|
||||||
// .resizable(false)
|
|
||||||
// .decorated(false)
|
|
||||||
// .build();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Create a dialog window
|
|
||||||
// let dialog = Dialog::new();
|
|
||||||
// dialog.set_title(Some("Custom Dialog"));
|
|
||||||
// dialog.set_default_size(300, 150);
|
|
||||||
//
|
|
||||||
// // Create a vertical box container for the dialog content
|
|
||||||
// let mut vbox =gtk4:: Box::new(Orientation::Horizontal, 10);
|
|
||||||
//
|
|
||||||
// // Add a label to the dialog
|
|
||||||
// let label = Label::new(Some("This is a custom dialog!"));
|
|
||||||
// vbox.append(&label);
|
|
||||||
//
|
|
||||||
// // Set the dialog content
|
|
||||||
// dialog.set_child(Some(&vbox));
|
|
||||||
//
|
|
||||||
// // Show the dialog
|
|
||||||
// dialog.present();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// let empty_array: [&str; 0] = [];;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// application.run_with_args(&empty_array);
|
|
||||||
//
|
|
||||||
// debug!("merged config result {:#?}", config);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue