From 1e48765ab39a679abcc4eac6927ad3bb58f7b438 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 4 Jun 2026 00:21:46 +0200 Subject: dirty, broken commit --- PLAN.md | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 PLAN.md (limited to 'PLAN.md') diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..baff505 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,135 @@ +# Dynamic Shell Autocompletion for Artists/Albums/Tracks + +## Problem + +`rsp play ` and `rsp queue ` accept freeform strings. No tab-completion for artists, albums, or tracks from the SQLite library DB. User must type full path or query blindly. + +## Approach: Direct DB read (no daemon dependency) + +Hidden CLI subcommand `rsp complete [prefix]` that: +1. Opens DB directly (same as `rsp scan` at cli.rs:204-205) +2. Queries with prefix match +3. Prints newline-separated results to stdout +4. Returns empty on error (never crash completion) + +Works with or without daemon running. SQLite prefix query is ~1ms. + +## Steps + +### 1. Add completion query methods to `Database` (`src/database.rs`) + +``` +pub fn complete_artists(&self, prefix: &str) -> SqlResult> +pub fn complete_albums(&self, prefix: &str) -> SqlResult> +pub fn complete_tracks(&self, prefix: &str) -> SqlResult> +``` + +SQL: +- artists: `SELECT name FROM artists WHERE name LIKE ? ORDER BY name` +- albums: `SELECT title FROM albums WHERE title LIKE ? ORDER BY title` +- tracks: `SELECT title FROM tracks WHERE title LIKE ? ORDER BY title` + +Prefix `"a"` → `LIKE 'a%'`. Limit results (e.g. 25). + +### 2. Add hidden `DbComplete` subcommand (`src/cli.rs`) + +``` +#[clap(hide = true)] +DbComplete { + entity: String, // "artists", "albums", "tracks" + prefix: Option, +} +``` + +Dispatch in `Cli::run()`: +``` +Commands::DbComplete { entity, prefix } => { + let config = Config::load()?; + let db = Database::open(&config)?; + let results = match entity.as_str() { ... }; + for r in results { println!("{r}"); } +} +``` + +Errors → silent empty (stderr) so completion never breaks. + +### 3. Filter `DbComplete` out of generated completions (like `Completions`) + +In `Completions` generation (cli.rs:238-253): filter `s.get_name() != "db-complete"`. + +### 4. Dynamic zsh completion function + +Replace `/usr/share/zsh/site-functions/_rsp` with a wrapper that: + +```zsh +#compdef rsp +# Static part (generated by clap) +_rsp_command() { ... } # clap-generated + +# Dynamic overrides +_rsp() { + case $line[1] in + play|queue) + if compset -P 1; then + # Subcommand → complete tracks/artists/albums + local -a suggestions + suggestions=(${(f)"$(rsp complete tracks "$words[CURRENT]")"}) + suggestions+=(${(f)"$(rsp complete artists "$words[CURRENT]")"}) + suggestions+=(${(f)"$(rsp complete albums "$words[CURRENT]")"}) + compadd -a suggestions + else + _rsp_command + fi + ;; + *) + _rsp_command + ;; + esac +} +``` + +For `play `, complete artists + albums + tracks. +Where artists have the biggest priority, then comes albums and at the end tracks. +Additionally, when we have autocompleted an artist, put a '/' after the name. Next autocompletions will autocomplete albums/tracks, do the same for albums. + +### 5. Update `Completions` generation to produce the wrapper + +In `cli.rs`, after `generate()` for zsh, append the dynamic wrapper code. The generated file becomes: `clap-generated-code` + `_rsp() { ... dynamic ... }`. + +Or simpler: write the wrapper as `completions/_rsp.dynamic` and concatenate in install.sh. + +### 6. Update `install.sh` + +Replace `rsp completions zsh | sudo tee ...` with: +```bash +(rsp completions zsh; echo; cat completions/_rsp) | sudo tee "$dest" +``` + +### 7. Update `TODO.md` + +Mark "[x] Dynamic autocompletion of artists, albums and tracks" + +### 8. Tests + +Add tests in `tests/database.rs`: +- `test_complete_artists_prefix` +- `test_complete_albums_prefix` +- `test_complete_tracks_prefix` +- `test_complete_empty_db` +- `test_complete_no_match` + +Need a test helper that creates a temp DB with known data, runs queries, checks results. + +## Files changed + +| File | Change | +|------|--------| +| `src/database.rs` | +3 pub methods (complete_artists/albums/tracks) | +| `src/cli.rs` | +DbComplete variant, +dispatch, +filter in Completions | +| `completions/_rsp.dynamic` (new) | zsh dynamic completion wrapper | +| `install.sh` | concatenate static + dynamic | +| `tests/database.rs` | +completion query tests | + +## Future: fish/bash + +Same pattern. Fish uses `complete -c rsp -n '__fish_seen_subcommand_from play' -a '(rsp complete tracks (commandline -ct))'`. Bash uses `COMPREPLY=($(compgen -W "$(rsp complete tracks "$cur")" -- "$cur"))`. Start with zsh only (user's shell). -- cgit v1.2.3