doc: Add install guide instructions.
This commit is contained in:
24
README.md
24
README.md
@@ -95,6 +95,30 @@ or at all:
|
|||||||
overlay on Wayland (layer-shell) and X11. Auto-detects your
|
overlay on Wayland (layer-shell) and X11. Auto-detects your
|
||||||
environment.
|
environment.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
See [docs/guides/install.md](docs/guides/install.md) for full details.
|
||||||
|
The short version:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install pikl
|
||||||
|
```
|
||||||
|
|
||||||
|
Or from source:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/maplecool/pikl-menu.git
|
||||||
|
cd pikl-menu
|
||||||
|
cargo install --path .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Guides
|
||||||
|
|
||||||
|
- **[Install](docs/guides/install.md):** cargo install, building from source
|
||||||
|
- **[App Launcher](docs/guides/app-launcher.md):** set up pikl as a
|
||||||
|
keyboard-driven app launcher on Hyprland, i3, macOS (Raycast), or
|
||||||
|
in a terminal
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -275,6 +275,36 @@ navigate directories without spawning new processes.
|
|||||||
query, or the viewport to do a lookup after each filter
|
query, or the viewport to do a lookup after each filter
|
||||||
pass.
|
pass.
|
||||||
|
|
||||||
|
- **Confirm-with-arguments (Shift+Enter).** Select an item
|
||||||
|
and also pass free-text arguments alongside it. Primary
|
||||||
|
use case: app launcher where you select `ls` and want to
|
||||||
|
pass `-la` to it. The output would include both the
|
||||||
|
selected item and the user-supplied arguments.
|
||||||
|
|
||||||
|
Open questions:
|
||||||
|
- UX flow: does the filter text become the args on
|
||||||
|
Shift+Enter? Or does Shift+Enter open a second input
|
||||||
|
field for args after selection? The filter-as-args
|
||||||
|
approach is simpler but conflates filtering and
|
||||||
|
argument input. A two-step flow (select, then type
|
||||||
|
args) is cleaner but adds a mode.
|
||||||
|
- Output format: separate field in the JSON output
|
||||||
|
(`"args": "-la"`)? Second line on stdout? Appended to
|
||||||
|
the label? Needs to be unambiguous for scripts.
|
||||||
|
- Should regular Enter with a non-empty filter that
|
||||||
|
matches exactly one item just confirm that item (current
|
||||||
|
behaviour), or should it also treat any "extra" text
|
||||||
|
as args? Probably not, too implicit.
|
||||||
|
- Keybind: Shift+Enter is natural, but some terminals
|
||||||
|
don't distinguish it from Enter. May need a fallback
|
||||||
|
like Ctrl+Enter or a normal-mode keybind.
|
||||||
|
|
||||||
|
This is a core feature (new keybind, new output field),
|
||||||
|
not just a launcher script concern. Fits naturally after
|
||||||
|
phase 4 (multi-select) since it's another selection
|
||||||
|
mode variant. The launcher script would assemble
|
||||||
|
`{selected} {args}` for execution.
|
||||||
|
|
||||||
## Future Ideas (Unscheduled)
|
## Future Ideas (Unscheduled)
|
||||||
|
|
||||||
These are things we've talked about or thought of. No
|
These are things we've talked about or thought of. No
|
||||||
@@ -306,3 +336,11 @@ commitment, no order.
|
|||||||
(optionally into a tmux session). Needs GUI frontend
|
(optionally into a tmux session). Needs GUI frontend
|
||||||
(phase 8) and frecency sorting.
|
(phase 8) and frecency sorting.
|
||||||
See `docs/use-cases/app-launcher.md`.
|
See `docs/use-cases/app-launcher.md`.
|
||||||
|
Setup guides: `docs/guides/app-launcher.md`.
|
||||||
|
- App description indexing: a tool or subcommand that
|
||||||
|
builds a local cache of binary descriptions from man
|
||||||
|
pages (`whatis`), .desktop file Comment fields, and
|
||||||
|
macOS Info.plist data. Solves the "whatis is too slow
|
||||||
|
to run per-keystroke" problem for the app launcher.
|
||||||
|
Could be a `pikl index` subcommand or a standalone
|
||||||
|
helper script.
|
||||||
|
|||||||
286
docs/guides/app-launcher.md
Normal file
286
docs/guides/app-launcher.md
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
# App Launcher Setup
|
||||||
|
|
||||||
|
Use pikl as a keyboard-driven application launcher. Bind
|
||||||
|
a hotkey, type a few characters, hit Enter, and your app
|
||||||
|
launches. This guide covers terminal, Hyprland, i3, and
|
||||||
|
macOS setups.
|
||||||
|
|
||||||
|
For the design rationale and feature roadmap, see
|
||||||
|
[the app launcher use case](../use-cases/app-launcher.md).
|
||||||
|
|
||||||
|
## Quick start: terminal
|
||||||
|
|
||||||
|
The simplest version. No GUI, no hotkeys, just an alias:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# ~/.bashrc or ~/.zshrc
|
||||||
|
alias launch='compgen -c | sort -u | pikl | xargs -I{} sh -c "{} &"'
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `launch`, type to filter, Enter to run the selection
|
||||||
|
in the background. That's it.
|
||||||
|
|
||||||
|
### With descriptions (experimental)
|
||||||
|
|
||||||
|
You can pull one-line descriptions from man pages using
|
||||||
|
`whatis`. This is noticeably slow on systems with
|
||||||
|
thousands of binaries (it shells out per binary), so treat
|
||||||
|
it as a nice-to-have rather than the default:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
launch-rich() {
|
||||||
|
compgen -c | sort -u | while IFS= read -r cmd; do
|
||||||
|
desc=$(whatis "$cmd" 2>/dev/null | head -1 | sed 's/.*- //')
|
||||||
|
printf '{"label":"%s","sublabel":"%s"}\n' "$cmd" "$desc"
|
||||||
|
done | pikl --format '{label} <dim>{sublabel}</dim>' \
|
||||||
|
| jq -r '.label' \
|
||||||
|
| xargs -I{} sh -c '{} &'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This works, but it's slow. Caching the output of the
|
||||||
|
`whatis` loop to a file and refreshing it periodically
|
||||||
|
would make it usable day-to-day. A built-in indexing
|
||||||
|
solution is on the roadmap but not built yet.
|
||||||
|
|
||||||
|
## Hyprland
|
||||||
|
|
||||||
|
Hyprland is a first-class target. pikl uses
|
||||||
|
`iced_layershell` to render as a Wayland layer-shell
|
||||||
|
overlay, so it floats above your desktop like rofi does.
|
||||||
|
|
||||||
|
### The launcher script
|
||||||
|
|
||||||
|
Save this somewhere in your PATH (e.g.
|
||||||
|
`~/.local/bin/pikl-launch`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
# pikl-launch: open pikl as a GUI app launcher
|
||||||
|
|
||||||
|
compgen -c | sort -u \
|
||||||
|
| pikl --mode gui \
|
||||||
|
| xargs -I{} sh -c '{} &'
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chmod +x ~/.local/bin/pikl-launch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keybinding
|
||||||
|
|
||||||
|
Add to `~/.config/hypr/hyprland.conf`:
|
||||||
|
|
||||||
|
```
|
||||||
|
bind = SUPER, SPACE, exec, pikl-launch
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload with `hyprctl reload` or restart Hyprland.
|
||||||
|
|
||||||
|
### With .desktop files (future)
|
||||||
|
|
||||||
|
When pikl gains .desktop file parsing (or a helper
|
||||||
|
script emits structured JSON from XDG desktop entries),
|
||||||
|
you'll get proper app names, descriptions, and categories
|
||||||
|
instead of raw binary names. The keybinding and workflow
|
||||||
|
stay the same, only the input to pikl changes.
|
||||||
|
|
||||||
|
## i3
|
||||||
|
|
||||||
|
i3 runs on X11, so pikl opens as an override-redirect
|
||||||
|
window rather than a layer-shell overlay. Same launcher
|
||||||
|
script, different keybinding syntax.
|
||||||
|
|
||||||
|
### The launcher script
|
||||||
|
|
||||||
|
Same `pikl-launch` script as Hyprland above. pikl
|
||||||
|
auto-detects X11 vs Wayland, so no changes needed.
|
||||||
|
|
||||||
|
### Keybinding
|
||||||
|
|
||||||
|
Add to `~/.config/i3/config`:
|
||||||
|
|
||||||
|
```
|
||||||
|
bindsym $mod+space exec --no-startup-id pikl-launch
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload with `$mod+Shift+r`.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- `--no-startup-id` prevents the i3 startup notification
|
||||||
|
cursor from spinning while pikl is open.
|
||||||
|
- If pikl doesn't grab focus automatically, you may need
|
||||||
|
to add an i3 rule:
|
||||||
|
```
|
||||||
|
for_window [class="pikl"] focus
|
||||||
|
```
|
||||||
|
|
||||||
|
## macOS with Raycast
|
||||||
|
|
||||||
|
Raycast is the best way to bind a global hotkey to pikl
|
||||||
|
on macOS. You create a script command that Raycast can
|
||||||
|
trigger from its search bar or a direct hotkey.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- [Raycast](https://raycast.com) installed
|
||||||
|
- pikl installed (`cargo install pikl`)
|
||||||
|
- pikl in your PATH (cargo's bin directory is usually
|
||||||
|
`~/.cargo/bin`, make sure it's in your shell PATH)
|
||||||
|
|
||||||
|
### Create the script command
|
||||||
|
|
||||||
|
Raycast script commands are shell scripts with a special
|
||||||
|
header. Create this file in your Raycast script commands
|
||||||
|
directory (usually `~/.config/raycast/scripts/` or
|
||||||
|
wherever you've configured it):
|
||||||
|
|
||||||
|
**`pikl-launch.sh`:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Required parameters:
|
||||||
|
# @raycast.schemaVersion 1
|
||||||
|
# @raycast.title App Launcher (pikl)
|
||||||
|
# @raycast.mode silent
|
||||||
|
# @raycast.packageName pikl
|
||||||
|
|
||||||
|
# Optional parameters:
|
||||||
|
# @raycast.icon :rocket:
|
||||||
|
|
||||||
|
# Scan /Applications for .app bundles, pipe to pikl, open the result
|
||||||
|
find /Applications ~/Applications -maxdepth 2 -name '*.app' 2>/dev/null \
|
||||||
|
| sed 's|.*/||; s|\.app$||' \
|
||||||
|
| sort -u \
|
||||||
|
| pikl --mode gui \
|
||||||
|
| xargs -I{} open -a "{}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chmod +x pikl-launch.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The `silent` mode tells Raycast not to show any output
|
||||||
|
window. pikl handles its own GUI.
|
||||||
|
|
||||||
|
### Assign a hotkey
|
||||||
|
|
||||||
|
1. Open Raycast preferences (Cmd+,)
|
||||||
|
2. Go to Extensions
|
||||||
|
3. Find "App Launcher (pikl)" under Script Commands
|
||||||
|
4. Click the hotkey field and press your preferred combo
|
||||||
|
(e.g. Ctrl+Space, Opt+Space, etc.)
|
||||||
|
|
||||||
|
### With structured JSON input
|
||||||
|
|
||||||
|
For a richer experience with app metadata, you can parse
|
||||||
|
the `Info.plist` files inside .app bundles:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Required parameters:
|
||||||
|
# @raycast.schemaVersion 1
|
||||||
|
# @raycast.title App Launcher (pikl)
|
||||||
|
# @raycast.mode silent
|
||||||
|
# @raycast.packageName pikl
|
||||||
|
|
||||||
|
for app in /Applications/*.app ~/Applications/*.app; do
|
||||||
|
[ -d "$app" ] || continue
|
||||||
|
name=$(basename "$app" .app)
|
||||||
|
# Pull the bundle identifier for metadata
|
||||||
|
bundle_id=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" \
|
||||||
|
"$app/Contents/Info.plist" 2>/dev/null)
|
||||||
|
printf '{"label":"%s","meta":{"bundle":"%s","path":"%s"}}\n' \
|
||||||
|
"$name" "$bundle_id" "$app"
|
||||||
|
done \
|
||||||
|
| pikl --mode gui \
|
||||||
|
| jq -r '.meta.path' \
|
||||||
|
| xargs -I{} open "{}"
|
||||||
|
```
|
||||||
|
|
||||||
|
This version gives pikl structured data to work with.
|
||||||
|
When pikl gains frecency sorting, your most-launched apps
|
||||||
|
will float to the top automatically.
|
||||||
|
|
||||||
|
### Alternative: skhd
|
||||||
|
|
||||||
|
If you don't use Raycast, [skhd](https://github.com/koekeishiya/skhd)
|
||||||
|
is a standalone hotkey daemon:
|
||||||
|
|
||||||
|
```
|
||||||
|
# ~/.config/skhd/skhdrc
|
||||||
|
ctrl + space : pikl-launch-mac.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `pikl-launch-mac.sh` is the same script as above,
|
||||||
|
minus the Raycast header comments.
|
||||||
|
|
||||||
|
## Customizing the launcher
|
||||||
|
|
||||||
|
These tips apply to all platforms.
|
||||||
|
|
||||||
|
### Filter fields
|
||||||
|
|
||||||
|
If your input includes structured JSON with metadata,
|
||||||
|
tell pikl which fields to search:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Search both label and sublabel when filtering
|
||||||
|
pikl --filter-fields label,sublabel
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
|
||||||
|
Run something when the launcher opens or when an item
|
||||||
|
is selected:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pikl --mode gui \
|
||||||
|
--on-select-exec 'jq -r .label >> ~/.local/state/pikl-launch-history'
|
||||||
|
```
|
||||||
|
|
||||||
|
This logs every launch to a history file, which could
|
||||||
|
feed into frecency sorting later.
|
||||||
|
|
||||||
|
### Starting in normal mode
|
||||||
|
|
||||||
|
If you prefer to land in vim normal mode (navigate first,
|
||||||
|
then `/` to filter):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pikl --mode gui --start-mode normal
|
||||||
|
```
|
||||||
|
|
||||||
|
## What's not built yet
|
||||||
|
|
||||||
|
A few things mentioned in this guide depend on features
|
||||||
|
that are still in development:
|
||||||
|
|
||||||
|
- **GUI frontend** (phase 8): the `--mode gui` flag and
|
||||||
|
layer-shell/X11 rendering. Until this ships, you can use
|
||||||
|
the TUI versions in a drop-down terminal (like tdrop,
|
||||||
|
kitty's `--single-instance`, or a quake-mode terminal).
|
||||||
|
- **Frecency sorting:** tracking launch frequency and
|
||||||
|
boosting common picks. On the roadmap.
|
||||||
|
- **.desktop file parsing:** structured input from XDG
|
||||||
|
desktop entries with proper names, icons, and categories.
|
||||||
|
On the roadmap.
|
||||||
|
- **Description caching/indexing:** a way to build and
|
||||||
|
maintain a local index of binary descriptions so the
|
||||||
|
launcher can show what each app does without the slow
|
||||||
|
`whatis` loop. On the roadmap.
|
||||||
|
|
||||||
|
## GNOME, KDE, and other desktops
|
||||||
|
|
||||||
|
These aren't supported as app launcher environments right
|
||||||
|
now. Hyprland, i3, and macOS are the environments the dev
|
||||||
|
team uses daily, so that's where the effort goes. The
|
||||||
|
main blocker for GNOME on Wayland is the lack of
|
||||||
|
layer-shell support, which means pikl can't render as an
|
||||||
|
overlay the same way it does on wlroots-based compositors.
|
||||||
|
|
||||||
|
If you use one of these environments and want to help,
|
||||||
|
PRs and discussion are welcome.
|
||||||
60
docs/guides/install.md
Normal file
60
docs/guides/install.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Installing pikl
|
||||||
|
|
||||||
|
## From crates.io (recommended)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install pikl
|
||||||
|
```
|
||||||
|
|
||||||
|
This builds the unified `pikl` binary with both TUI and
|
||||||
|
GUI frontends. You'll need a working Rust toolchain. If
|
||||||
|
you don't have one, [rustup](https://rustup.rs) is the
|
||||||
|
way to go.
|
||||||
|
|
||||||
|
### TUI only
|
||||||
|
|
||||||
|
If you only want the terminal interface and don't want to
|
||||||
|
pull in GUI dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install pikl --no-default-features --features tui
|
||||||
|
```
|
||||||
|
|
||||||
|
## From source
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/maplecool/pikl-menu.git
|
||||||
|
cd pikl-menu
|
||||||
|
cargo install --path .
|
||||||
|
```
|
||||||
|
|
||||||
|
This builds and installs the `pikl` binary into your
|
||||||
|
cargo bin directory (usually `~/.cargo/bin/`).
|
||||||
|
|
||||||
|
## Package managers
|
||||||
|
|
||||||
|
We'd like pikl to be available in package managers like
|
||||||
|
the AUR and Homebrew, but honestly haven't set that up
|
||||||
|
before and aren't sure when we'll get to it. TBD.
|
||||||
|
|
||||||
|
If you package pikl for a distro or package manager, open
|
||||||
|
an issue and we'll link it here.
|
||||||
|
|
||||||
|
## Verify it works
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo -e "hello\nworld\ngoodbye" | pikl
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see a filterable list in insert mode. Type to
|
||||||
|
filter, use arrow keys to navigate, Enter to select,
|
||||||
|
Escape to quit. The selected item prints to stdout.
|
||||||
|
|
||||||
|
pikl starts in insert mode by default (type to filter
|
||||||
|
immediately). Press Ctrl+N to switch to normal mode for
|
||||||
|
vim-style navigation (j/k, gg, G, Ctrl+D/U). Ctrl+E
|
||||||
|
switches back to insert mode. You can also start in
|
||||||
|
normal mode with `--start-mode normal`.
|
||||||
|
|
||||||
|
Note: Ctrl+I is not the same as Tab. pikl treats these
|
||||||
|
as distinct inputs.
|
||||||
Reference in New Issue
Block a user