feat: update README and add documentation for installation, configuration, usage, and plugin development
This commit is contained in:
81
README.md
81
README.md
@@ -1,56 +1,41 @@
|
||||
# K-Launcher
|
||||
# k-launcher
|
||||
|
||||
K-Launcher is a lightweight, GPU-accelerated command palette for Linux (Wayland/X11), macOS, and Windows. It reimagines the "Spotlight" experience through the lens of Frutiger Aero—focusing on gloss, glass, and skeuomorphism—powered by a non-blocking, multi-threaded Rust kernel.
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
- Zero Webview: No Chromium, no Electron. Every pixel is rendered via WGPU (Iced) for sub-5ms input-to-render latency.
|
||||
|
||||
- Async-First: Search queries never block the UI. If the file-searcher is indexing, the calculator still feels instant.
|
||||
|
||||
- The "Aero" Standard: Deep support for Gaussian blur (via Layer Shell), linear gradients, and high-gloss textures.
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
We are utilizing a "Hub-and-Spoke" model within a Cargo Workspace. The k-launcher-kernel acts as the central hub, dispatching user input to various "Spokes" (Plugins).
|
||||
|
||||
### The Crate Hierarchy
|
||||
|
||||
| Crate | Responsibility | Key Dependencies |
|
||||
| -------------------------- | --------------------------------------------------------- | -------------------------------------- |
|
||||
| **`k-launcher`** | The entry-point binary. Glues everything together. | `k-launcher-ui`, `k-launcher-kernel` |
|
||||
| **`k-launcher-ui`** | The Iced-based view layer. Handles animations/theming. | `iced`, `lyon` (for vector paths) |
|
||||
| **`k-launcher-kernel`** | The "Brain." Manages state, history, and plugin dispatch. | `tokio`, `tracing` |
|
||||
| **`k-launcher-os-bridge`** | OS-specific windowing (Layer Shell for Wayland, Win32). | `iced_layershell`, `raw-window-handle` |
|
||||
| **`plugins/*`** | Individual features (Calc, Files, Apps, Web). | `plugin-api` (Shared traits) |
|
||||
|
||||
## Data & Communication Flow
|
||||
|
||||
K-Launcher operates on an Event loop.
|
||||
A lightweight, GPU-accelerated command palette for Linux (Wayland/X11). Zero Electron — every pixel rendered via WGPU. Async search that never blocks the UI.
|
||||
|
||||
```
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant UI as k-launcher-ui
|
||||
participant Kernel as k-launcher-kernel
|
||||
participant Plugins as plugin-file-search
|
||||
|
||||
User->>UI: Types "p"
|
||||
UI->>Kernel: QueryUpdate("p")
|
||||
par Parallel Search
|
||||
Kernel->>Plugins: async search("p")
|
||||
Plugins-->>Kernel: List<SearchResult>
|
||||
end
|
||||
Kernel->>UI: NewResults(Vec)
|
||||
UI-->>User: Render Glass Result List
|
||||
[screenshot placeholder]
|
||||
```
|
||||
|
||||
## Technical Specifications
|
||||
## Quick Start
|
||||
|
||||
To ensure "Plug and Play" capability, all features must implement the `Plugin` trait. This allows the user to swap the default `file-searcher` for something like `fzf` or `plocate` without recompiling the UI.
|
||||
```bash
|
||||
git clone https://github.com/GKaszewski/k-launcher
|
||||
cd k-launcher
|
||||
cargo build --release
|
||||
./target/release/k-launcher
|
||||
```
|
||||
|
||||
To achieve the 2000s aesthetic without a browser:
|
||||
## Keybinds
|
||||
|
||||
- Background Blur: On Wayland, we request blur through the org_kde_kwin_blur or fractional-scale protocols.
|
||||
- Shaders: We will use Iced’s canvas to draw glossy "shine" overlays that respond to mouse hovering.
|
||||
- Icons: We will prefer .svg and .png with high-depth shadows over flat icon fonts.
|
||||
| Key | Action |
|
||||
| --------- | --------------- |
|
||||
| Type | Filter results |
|
||||
| `↑` / `↓` | Navigate |
|
||||
| `Enter` | Launch selected |
|
||||
| `Escape` | Close |
|
||||
|
||||
## Built-in Plugins
|
||||
|
||||
| Trigger | Plugin | Example |
|
||||
| ----------------- | ------ | -------------- |
|
||||
| (any text) | Apps | `firefox` |
|
||||
| number/expression | Calc | `2^10 + 5` |
|
||||
| `>` prefix | Shell | `> echo hello` |
|
||||
| `/` or `~/` | Files | `~/Documents` |
|
||||
|
||||
## Docs
|
||||
|
||||
- [Installation](docs/install.md)
|
||||
- [Usage & Keybinds](docs/usage.md)
|
||||
- [Configuration & Theming](docs/configuration.md)
|
||||
- [Plugin Development](docs/plugin-development.md)
|
||||
|
||||
45
docs/configuration.md
Normal file
45
docs/configuration.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Configuration
|
||||
|
||||
Config file: `~/.config/k-launcher/config.toml`
|
||||
|
||||
The file is optional — all fields have defaults and missing sections fall back to defaults automatically. Create it manually if you want to customize behavior.
|
||||
|
||||
## Full Annotated Example
|
||||
|
||||
```toml
|
||||
[window]
|
||||
width = 600.0 # window width in logical pixels
|
||||
height = 400.0 # window height in logical pixels
|
||||
decorations = false # show window title bar / frame
|
||||
transparent = true # allow background transparency
|
||||
resizable = false # allow manual resizing
|
||||
|
||||
[appearance]
|
||||
# RGBA: r/g/b are 0–255 as floats, a is 0.0–1.0
|
||||
background_rgba = [20.0, 20.0, 30.0, 0.9] # main background
|
||||
border_rgba = [229.0, 125.0, 33.0, 1.0] # accent/border color
|
||||
border_width = 1.0 # border thickness in pixels
|
||||
border_radius = 8.0 # corner radius of the window
|
||||
search_font_size = 18.0 # font size of the search input
|
||||
title_size = 15.0 # font size of result titles
|
||||
desc_size = 12.0 # font size of result descriptions
|
||||
row_radius = 4.0 # corner radius of result rows
|
||||
placeholder = "Search..." # search input placeholder text
|
||||
|
||||
[search]
|
||||
max_results = 8 # maximum results shown at once
|
||||
|
||||
[plugins]
|
||||
calc = true # math expression evaluator
|
||||
cmd = true # shell command runner (> prefix)
|
||||
files = true # filesystem browser (/ or ~/ prefix)
|
||||
apps = true # XDG application launcher
|
||||
```
|
||||
|
||||
## RGBA Format
|
||||
|
||||
Colors use `[r, g, b, a]` arrays where:
|
||||
- `r`, `g`, `b` — red, green, blue channels as floats **0.0–255.0**
|
||||
- `a` — alpha (opacity) as a float **0.0–1.0**
|
||||
|
||||
Example — semi-transparent white: `[255.0, 255.0, 255.0, 0.5]`
|
||||
57
docs/install.md
Normal file
57
docs/install.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Installation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Rust** stable toolchain — install via [rustup](https://rustup.rs)
|
||||
- **git**
|
||||
- A **Wayland** or **X11** compositor (Linux)
|
||||
|
||||
## Build from Source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/GKaszewski/k-launcher
|
||||
cd k-launcher
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
Binary location: `target/release/k-launcher`
|
||||
|
||||
### Optional: install to PATH
|
||||
|
||||
```bash
|
||||
cp target/release/k-launcher ~/.local/bin/
|
||||
```
|
||||
|
||||
Ensure `~/.local/bin` is in your `$PATH`.
|
||||
|
||||
## Autostart
|
||||
|
||||
### Hyprland
|
||||
|
||||
Add to `~/.config/hypr/hyprland.conf`:
|
||||
|
||||
```
|
||||
exec-once = k-launcher
|
||||
```
|
||||
|
||||
### systemd user service
|
||||
|
||||
Create `~/.config/systemd/user/k-launcher.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=k-launcher command palette
|
||||
|
||||
[Service]
|
||||
ExecStart=%h/.local/bin/k-launcher
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
```
|
||||
|
||||
Then enable it:
|
||||
|
||||
```bash
|
||||
systemctl --user enable --now k-launcher
|
||||
```
|
||||
132
docs/plugin-development.md
Normal file
132
docs/plugin-development.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Plugin Development
|
||||
|
||||
Plugins are Rust crates that implement the `Plugin` trait from `k-launcher-kernel`. They run concurrently — the kernel fans out every query to all enabled plugins and merges results by score.
|
||||
|
||||
> Note: plugins are compiled into the binary at build time. There is no dynamic loading support yet.
|
||||
|
||||
## Step-by-Step
|
||||
|
||||
### 1. Create a new crate in the workspace
|
||||
|
||||
```bash
|
||||
cargo new --lib crates/plugins/plugin-hello
|
||||
```
|
||||
|
||||
Add it to the workspace root `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[workspace]
|
||||
members = [
|
||||
# ...existing members...
|
||||
"crates/plugins/plugin-hello",
|
||||
]
|
||||
```
|
||||
|
||||
### 2. Add dependencies
|
||||
|
||||
`crates/plugins/plugin-hello/Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
k-launcher-kernel = { path = "../../k-launcher-kernel" }
|
||||
async-trait = "0.1"
|
||||
```
|
||||
|
||||
### 3. Implement the `Plugin` trait
|
||||
|
||||
`crates/plugins/plugin-hello/src/lib.rs`:
|
||||
|
||||
```rust
|
||||
use async_trait::async_trait;
|
||||
use k_launcher_kernel::{
|
||||
LaunchAction, Plugin, PluginName, ResultId, ResultTitle, Score, SearchResult,
|
||||
};
|
||||
|
||||
pub struct HelloPlugin;
|
||||
|
||||
impl HelloPlugin {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Plugin for HelloPlugin {
|
||||
fn name(&self) -> PluginName {
|
||||
"hello"
|
||||
}
|
||||
|
||||
async fn search(&self, query: &str) -> Vec<SearchResult> {
|
||||
if !query.starts_with("hello") {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
vec![SearchResult {
|
||||
id: ResultId::new("hello:world"),
|
||||
title: ResultTitle::new("Hello, World!"),
|
||||
description: Some("A greeting from the hello plugin".to_string()),
|
||||
icon: None,
|
||||
score: Score::new(80),
|
||||
action: LaunchAction::CopyToClipboard("Hello, World!".to_string()),
|
||||
on_select: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Wire up in main.rs
|
||||
|
||||
`crates/k-launcher/src/main.rs` — add alongside the existing plugins:
|
||||
|
||||
```rust
|
||||
use plugin_hello::HelloPlugin;
|
||||
|
||||
// inside main():
|
||||
plugins.push(Arc::new(HelloPlugin::new()));
|
||||
```
|
||||
|
||||
Also add the dependency to `crates/k-launcher/Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
plugin-hello = { path = "../plugins/plugin-hello" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
### `SearchResult` Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | `ResultId` | Unique stable ID (e.g. `"apps:firefox"`) |
|
||||
| `title` | `ResultTitle` | Primary display text |
|
||||
| `description` | `Option<String>` | Secondary line shown below title |
|
||||
| `icon` | `Option<String>` | Icon name or path (currently unused in renderer) |
|
||||
| `score` | `Score(u32)` | Sort priority — higher wins |
|
||||
| `action` | `LaunchAction` | What happens on `Enter` |
|
||||
| `on_select` | `Option<Arc<dyn Fn()>>` | Optional side-effect on selection (e.g. frecency bump) |
|
||||
|
||||
### `LaunchAction` Variants
|
||||
|
||||
| Variant | Behavior |
|
||||
|---------|----------|
|
||||
| `SpawnProcess(String)` | Launch a process directly (e.g. app exec string) |
|
||||
| `SpawnInTerminal(String)` | Run command inside a terminal emulator |
|
||||
| `OpenPath(String)` | Open a file or directory with `xdg-open` |
|
||||
| `CopyToClipboard(String)` | Copy text to clipboard |
|
||||
| `Custom(Arc<dyn Fn()>)` | Arbitrary closure |
|
||||
|
||||
### Scoring Guidance
|
||||
|
||||
| Score range | Match type |
|
||||
|-------------|-----------|
|
||||
| 100 | Exact match |
|
||||
| 90–99 | Calc/command result (always relevant) |
|
||||
| 80 | Prefix match |
|
||||
| 70 | Abbreviation match |
|
||||
| 60 | Substring match |
|
||||
| 50 | Keyword / loose match |
|
||||
|
||||
The kernel sorts all results from all plugins by score descending and truncates to `max_results` (default: 8).
|
||||
50
docs/usage.md
Normal file
50
docs/usage.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Usage
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
k-launcher
|
||||
```
|
||||
|
||||
## Keybinds
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| Type | Filter results |
|
||||
| `↑` / `↓` | Navigate list |
|
||||
| `Enter` | Launch selected result |
|
||||
| `Escape` | Close launcher |
|
||||
|
||||
## Built-in Plugins
|
||||
|
||||
### Apps
|
||||
|
||||
Type any app name to search installed applications. An empty query shows your most frequently launched apps (frecency-ranked top results).
|
||||
|
||||
### Calc
|
||||
|
||||
Type a math expression — the result appears instantly and is copied to clipboard on `Enter`.
|
||||
|
||||
```
|
||||
2^10 + 5 → 1029
|
||||
sqrt(144) → 12
|
||||
sin(pi / 2) → 1
|
||||
```
|
||||
|
||||
### Shell Command
|
||||
|
||||
Prefix your input with `>` to run a shell command in a terminal:
|
||||
|
||||
```
|
||||
> echo hello
|
||||
> htop
|
||||
```
|
||||
|
||||
### Files
|
||||
|
||||
Start your query with `/` or `~/` to browse the filesystem:
|
||||
|
||||
```
|
||||
/etc/hosts
|
||||
~/Documents/report.pdf
|
||||
```
|
||||
Reference in New Issue
Block a user