feat: restructure k-launcher workspace and add core functionality
- Updated Cargo.toml to include a new k-launcher crate and reorganized workspace members. - Introduced a README.md file detailing the project philosophy, architecture, and technical specifications. - Implemented a new Kernel struct in k-launcher-kernel for managing plugins and search functionality. - Created a Plugin trait for plugins to implement, allowing for asynchronous search operations. - Developed k-launcher-ui with an Iced-based UI for user interaction, including search input and result display. - Added AppsPlugin and CalcPlugin to handle application launching and basic calculations, respectively. - Established a theme module for UI styling, focusing on an Aero aesthetic. - Removed unnecessary main.rs files from plugin crates, streamlining the project structure.
This commit is contained in:
83
crates/plugins/plugin-calc/src/lib.rs
Normal file
83
crates/plugins/plugin-calc/src/lib.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use k_launcher_kernel::{Plugin, PluginName, ResultId, ResultTitle, Score, SearchResult};
|
||||
|
||||
pub struct CalcPlugin;
|
||||
|
||||
impl CalcPlugin {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CalcPlugin {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn should_eval(query: &str) -> bool {
|
||||
query
|
||||
.chars()
|
||||
.next()
|
||||
.map(|c| c.is_ascii_digit() || c == '(' || c == '-')
|
||||
.unwrap_or(false)
|
||||
|| query.starts_with('=')
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Plugin for CalcPlugin {
|
||||
fn name(&self) -> PluginName {
|
||||
"calc"
|
||||
}
|
||||
|
||||
async fn search(&self, query: &str) -> Vec<SearchResult> {
|
||||
if !should_eval(query) {
|
||||
return vec![];
|
||||
}
|
||||
let expr = query.strip_prefix('=').unwrap_or(query);
|
||||
match evalexpr::eval_number(expr) {
|
||||
Ok(n) if n.is_finite() => {
|
||||
let display = if n.fract() == 0.0 {
|
||||
format!("= {}", n as i64)
|
||||
} else {
|
||||
format!("= {n}")
|
||||
};
|
||||
vec![SearchResult {
|
||||
id: ResultId::new("calc-result"),
|
||||
title: ResultTitle::new(display),
|
||||
description: None,
|
||||
icon: None,
|
||||
score: Score::new(90),
|
||||
on_execute: Arc::new(|| {}),
|
||||
}]
|
||||
}
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn calc_valid_expr() {
|
||||
let p = CalcPlugin::new();
|
||||
let results = p.search("2+2").await;
|
||||
assert_eq!(results[0].title.as_str(), "= 4");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn calc_non_numeric_returns_empty() {
|
||||
let p = CalcPlugin::new();
|
||||
assert!(p.search("firefox").await.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn calc_bad_expr_returns_empty() {
|
||||
let p = CalcPlugin::new();
|
||||
assert!(p.search("1/0").await.is_empty());
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
fn main() {}
|
||||
|
||||
Reference in New Issue
Block a user