doc: Add project design, dev plan, coding standards, and use cases.

This commit is contained in:
2026-03-13 21:47:37 -04:00
parent 24f6635927
commit b4129eaeaf
5 changed files with 1364 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
# Use Case: App Launcher
A global-hotkey application launcher that replaces
Spotlight, Alfred, or rofi's drun mode. Bind a key
combo to open pikl as a GUI overlay, fuzzy-filter
binaries from PATH, hit Enter to launch.
## What It Looks Like
1. User presses a global hotkey (Super on Linux,
Cmd+Space on macOS).
2. pikl opens as a centered overlay.
3. The list is pre-populated with binaries from PATH
(or parsed .desktop entries).
4. User types to fuzzy-filter. Frecency sorting puts
frequently launched apps at the top.
5. Enter launches the selection. Escape dismisses.
This should feel instant. Sub-100ms to first paint.
## How It Works With pikl
### Basic Version
```sh
# Collect PATH binaries, open pikl, run selection
compgen -c | sort -u \
| pikl --mode gui \
| xargs -I{} sh -c '{} &'
```
### With tmux Integration
On select, create a new tmux session running the
chosen binary, then switch to it. Keeps everything
inside tmux for window management.
```sh
compgen -c | sort -u \
| pikl --mode gui \
--on-select 'cmd=$(cat);
tmux new-session -d -s "$cmd" "$cmd" &&
tmux switch-client -t "$cmd"'
```
### With .desktop Files
Parse XDG .desktop entries for proper app names and
icons instead of raw binary names:
```sh
# Hypothetical helper that emits JSON items
desktop-entries --json \
| pikl --mode gui \
--format '{icon} {label} <dim>{sublabel}</dim>'
```
Input would look like:
```jsonl
{"label": "Firefox", "sublabel": "Web Browser",
"meta": {"exec": "firefox", "desktop": "firefox.desktop"},
"icon": "/usr/share/icons/.../firefox.png"}
{"label": "Alacritty", "sublabel": "Terminal",
"meta": {"exec": "alacritty"},
"icon": "/usr/share/icons/.../alacritty.png"}
```
### Hyprland / Sway Keybinding
```
bind = SUPER, SPACE, exec, app-launcher.sh
```
On macOS, use skhd or a similar hotkey daemon.
### Fallback: TUI Mode
Before the GUI frontend exists, this works today in
a drop-down terminal:
```sh
# Bind to a hotkey that opens a terminal running:
compgen -c | sort -u | pikl | xargs -I{} sh -c '{} &'
```
## What pikl Features This Exercises
| Feature | Phase | How It's Used |
|---|---|---|
| GUI overlay | 8 | Centered layer-shell popup |
| Fuzzy filtering | 2 | Filter thousands of binaries |
| Frecency sorting | future | Boost frequently launched apps |
| on-select hook | 3 | Spawn or exec the selection |
| Structured I/O | 3 | .desktop metadata, icons |
| Fast startup | 1 | Must feel instant |
| Icon rendering | 8 | App icons in the list |
| Groups | 9 | Categories (dev, media, etc) |
## Stretch Goals
- **Frecency:** track launch counts per binary, sort
by frequency so your top apps float to the top.
This is the single biggest UX improvement over a
plain sorted list.
- **Categories:** group items by type. Dev tools,
browsers, media, system. Parsed from .desktop
Categories field or manually tagged.
- **Recent files:** a second section below apps
showing recently opened files. Needs a separate
data source (zeitgeist, custom tracker, etc).
- **Calculator / snippets:** if the query doesn't
match any app, treat it as a math expression or
snippet expansion. Scope creep, but it is what
makes launchers sticky.
## Platform Notes
- **Linux (Wayland):** layer-shell overlay. Global
hotkey via the compositor (Hyprland bind, Sway
bindsym). This is the primary target.
- **Linux (X11):** override-redirect window. Global
hotkey via xbindkeys or similar.
- **macOS:** no layer-shell. Needs a borderless
window with proper focus handling. Global hotkey
via skhd or a native Swift shim. Secondary target.
## Open Questions
- How to handle apps that need a terminal (e.g.
htop, vim). Detect from .desktop Terminal=true and
wrap in the user's preferred terminal emulator?
- Should the launcher persist as a background process
for faster re-open, or cold-start each time?
Background process is snappier but uses memory.
- PATH scanning: rescan on every open, or cache with
inotify/FSEvents on PATH directories?

View File

@@ -0,0 +1,145 @@
# Use Case: Wallpaper Picker
A keyboard-driven wallpaper picker for Hyprland that
previews wallpapers live on the desktop as you browse.
This is a first-class use case for pikl-menu: it
exercises structured I/O, lifecycle hooks, debouncing,
and the GUI overlay.
## What It Looks Like
1. User presses a keybind. pikl opens as a layer-shell
overlay on the focused monitor.
2. A list of wallpapers appears, filterable by typing.
3. Navigating the list applies each wallpaper live to
the desktop behind the overlay (via hyprpaper IPC).
4. Enter confirms. The wallpaper stays, overlay closes.
5. Escape cancels. The wallpaper reverts to whatever
was set before the picker opened.
The overlay is semi-transparent so the user sees the
real wallpaper behind it. No preview pane needed.
## How It Works With pikl
The wallpaper picker is not a standalone app. It is a
shell script (or a small wrapper) that pipes items into
pikl and uses hooks for the live preview behaviour.
### Basic Version
```sh
# List wallpapers as JSON, pipe to pikl with hooks
find ~/Pictures/walls -type f \
-name '*.jpg' -o -name '*.png' -o -name '*.webp' \
| jq -Rc '{label: (. | split("/") | last),
sublabel: (. | split("/") | .[:-1]
| join("/")), meta: {path: .}}' \
| pikl --mode gui \
--on-open 'hyprctl hyprpaper listactive
| head -1 > /tmp/pikl-wall-orig' \
--on-hover 'jq -r .meta.path
| xargs -I{} hyprctl hyprpaper
wallpaper "DP-4, {}"' \
--on-cancel 'cat /tmp/pikl-wall-orig
| cut -d: -f2 | xargs -I{}
hyprctl hyprpaper wallpaper "DP-4, {}"' \
--on-hover-debounce 100
```
### With a Manifest
For a reusable setup, use a pikl manifest file:
```toml
# ~/.config/pikl/wallpaper.toml
[hooks]
on-open = "save-current-wallpaper.sh"
on-hover = '''
jq -r .meta.path \
| xargs -I{} hyprctl hyprpaper \
wallpaper "DP-4, {}"
'''
on-cancel = "restore-wallpaper.sh"
on-hover-debounce = 100
[display]
format = "{label} <dim>{sublabel}</dim>"
```
```sh
find ~/Pictures/walls -type f \( \
-name '*.jpg' -o -name '*.png' \) \
| to-json-items \
| pikl --manifest ~/.config/pikl/wallpaper.toml \
--mode gui
```
### Modes
Different invocations cover different workflows:
**Browse:** open the picker, filter and select.
```sh
find ~/Pictures/walls -type f ... | pikl ...
```
**History:** pipe wallpaper history instead of a
directory scan. Same hooks, different input source.
```sh
cat ~/.local/state/wallpaper-history.jsonl \
| pikl --manifest ~/.config/pikl/wallpaper.toml \
--mode gui
```
**Random:** no pikl needed, just a shell one-liner.
```sh
find ~/Pictures/walls -type f ... \
| shuf -n1 \
| xargs -I{} hyprctl hyprpaper wallpaper "DP-4, {}"
```
**Restore:** read the last state file, apply it.
Also just a shell script, no pikl.
### Hyprland Keybindings
```
bind = $mod CTRL, B, exec, wallpicker browse
bind = $mod SHIFT, B, exec, wallpicker random
bind = $mod, B, exec, wallpicker copy
```
## What pikl Features This Exercises
| Feature | Phase | How It's Used |
|---|---|---|
| GUI overlay | 8 | Layer-shell on Wayland |
| Structured I/O | 3 | JSON items with metadata |
| on-hover hook | 3 | Live wallpaper preview |
| on-open hook | 3 | Save current wallpaper |
| on-cancel hook | 3 | Revert wallpaper |
| Hook debouncing | 3 | Don't flood hyprctl |
| Fuzzy filtering | 2 | Filter by filename |
| Manifest files | 3 | Reusable config |
| Watched sources | 7 | Live update on new files |
| Sessions | 6 | Remember last position |
## Open Questions
- Should pikl support image thumbnails in the item
list? Useful here but adds complexity. Could be a
GUI-only feature using the icon field.
- Debounce timing: 100ms feels right for hyprctl IPC.
Might need tuning for slower wallpaper daemons.
- Multi-monitor: the on-hover hook needs to know which
monitor to target. Could come from a CLI flag or
from hyprctl's focused monitor.
- History management: pikl sessions handle state, but
wallpaper history (which wallpapers were set when)
is the wrapper script's responsibility. Keep it
simple: append to a JSONL file.