Files
tinyproject-monorepo/prg/sjaur/README.md
T
2026-10-02 15:29:35 +02:00

202 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# sjaur
Fast, fuzzy **TUI search for the [Arch User Repository](https://aur.archlinux.org) and the official Arch Linux repositories** — with real package installation, built on the official AUR metadata dump and your local pacman sync databases.
```
┌ Search: firfox ────────────────────────────────────────────────────────┐
├──────────────────────────────────────┬─────────────────────────────────┤
│ firefox 130.0-1 +3500 │ Name firefox │
│ firefox-nightly 131.0b1 +120 │ Version 130.0-1 │
│ firefox-wayland 129.0 +90 │ Maintainer jonas │
│ … │ Votes 3500 │
│ │ Popularity 214.53 │
│ │ … │
├──────────────────────────────────────┴─────────────────────────────────┤
│ 9 results · 24 ms · cache 2.1 hours old │
└────────────────────────────────────────────────────────────────────────┘
```
Typo-tolerant ranking across name, description, maintainer, keywords,
provides, and dependency fields — all served from a local snapshot, so
searching never touches the network.
## Install
```bash
cd sjaur
python -m venv .venv
.venv/bin/pip install .
```
Then link the executable onto your `PATH` (or copy it):
```bash
sudo ln -s "$(pwd)/.venv/bin/sjaur" /usr/local/bin/sjaur
# or, without root:
mkdir -p ~/.local/bin && ln -s "$(pwd)/.venv/bin/sjaur" ~/.local/bin/sjaur
```
Requirements: Python ≥ 3.10 and Linux (deps: `rapidfuzz`, `textual`).
## Usage
```bash
sjaur # launch the TUI
sjaur --update # force a metadata refresh, then exit
sjaur --version
sjaur --help
```
Optional:
- `--cache-dir <dir>` overrides the cache location (default `~/.cache/sjaur`)
- `--no-repos` searches the AUR only (skip official repository packages)
- `--repos-dir <dir>` overrides the pacman sync database directory
(default `/var/lib/pacman/sync`)
## Official repository packages
By default, sjaur merges the packages of your **local pacman sync databases**
(`core`, `extra`, …) into the search index. They appear with a repository
badge (`firefox [extra]`), can be installed directly via
`sudo pacman -S <name>` (`i` in the TUI — no build step, pacman asks for
confirmation), and work with all search features including `@maintainer`
(the packager email is used, e.g. `@heftig`). Votes, popularity, and
out-of-date status are AUR-only concepts and are hidden for repo packages.
The databases are read-only and stay where pacman manages them; run
`pacman -Sy` as usual to refresh them. On systems without sync databases,
sjaur falls back to AUR-only search with a warning.
## Search syntax
| Query | Meaning |
| --------------------------- | ---------------------------------------------------------------- |
| `firefox` | fuzzy search across all package fields |
| `@max_musterman` | fuzzy-search the **maintainer** field |
| `@max_musterman firefox` | maintainer search combined with a normal search |
| `@john python editor` | maintainer query is `john`; `python editor` is the normal query |
Rules:
- Only the **first whitespace-delimited word** after `@` is the maintainer
query; everything after it is the normal search.
- Matching stays fuzzy: `@max_musterman` also finds `max_mustermann`,
`max-musterman` or `max_musterman123` — no exact match required.
- With `@`, the result score is
`maintainer_similarity × 0.65 + package_score × 0.35`, so maintainer matches
dominate while the text query still orders the results.
- The parser is table-driven, so future operators (e.g. `#keyword`,
`depends:python`) can be added without touching the search engine.
### Live search
Results update **while you type** — no Enter needed:
1. On every keystroke the current list is instantly narrowed client-side
(packages that no longer match disappear immediately).
2. After a short pause (0.18 s), the full fuzzy search over all fields runs
in the background and refines the list.
Editing or retyping a recent query restores its result set instantly from an
in-memory cache; the status line shows `live` while you are typing and the
measured search time once the background search has finished.
## Keys
| Key | Action |
| ---------------------- | ----------------------------------------- |
| typing | **live search** — results update on every keystroke |
| `↑` / `↓` | navigate results |
| `enter` | open package details (`esc` returns) |
| `i` / `ctrl+i` | install the selected package |
| `tab` / `shift+tab` | switch between search field and results |
| `page up` / `page down`, `home` / `end` | scroll / jump |
| `ctrl+r` | reload AUR metadata now |
| `f1` | help overlay |
| `esc` | clear search / leave current view |
| `ctrl+c` | quit |
## Installing packages
With a package highlighted, press `i` (or `ctrl+i`) and confirm with `y`.
sjaur then runs the classic AUR workflow with plain system tools:
1. **Clone** the package repository from
`https://aur.archlinux.org/<name>.git` into `~/.cache/sjaur/build/<name>`
(an existing clone is **reused**; confirm with `u` instead of `y` to
hard-reset and update it first).
2. **Review** the PKGBUILD — it is printed to the terminal, and you can open
it in `$EDITOR` before deciding. **Always read it**: the AUR ships
user-produced build scripts.
3. **Build & install** via `makepkg --syncdeps --install`. pacman's
confirmation, the sudo password prompt, and the whole build output appear
directly in your terminal; the TUI suspends and resumes afterwards.
The result is reported in the terminal; press Enter to return to sjaur.
If anything fails (clone error, dependency problem, aborted build), the
message explains what happened and the TUI keeps running.
> **Security note:** AUR packages are user-produced content. sjaur shows the
> PKGBUILD (and any bundled install scripts) before building — never install
> packages whose build steps you do not understand.
## Package details
Selecting a package shows everything the local snapshot knows — name,
version, description, maintainer, votes, popularity, last modified,
out-of-date status, upstream URL, AUR page, licenses, groups, keywords,
depends, makedepends, checkdepends, optdepends, provides, conflicts, replaces
— without any additional network request.
## Cache behavior
`sjaur` keeps a decompressed copy of the official extended metadata dump
(`https://aur.archlinux.org/packages-meta-ext-v1.json.gz`) in:
```
~/.cache/sjaur/packages-meta-ext-v1.json
```
- At startup the cache's **modification time** is checked; if it is younger
than **24 hours** it is used as-is, otherwise a fresh dump is downloaded.
- The replacement is **atomic**: the dump is downloaded to a temporary file,
decompressed, validated as JSON, and only then swapped in with
`os.replace`. A failed download never destroys a working cache.
- If the download fails but a (stale) cache exists, the old cache is used and
a warning is shown. If there is no usable cache at all, `sjaur` exits with
a clear error.
- `SJAUR_CACHE_DIR` overrides the cache directory (XDG `XDG_CACHE_HOME` is
respected).
## Development
```bash
python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest # run the test suite
.venv/bin/mypy src # type-check
```
Project layout:
```
sjaur/
├── src/sjaur/
│ ├── cli.py argument parsing and startup flow
│ ├── cache.py download / decompress / validate / atomic replace
│ ├── metadata.py typed Package model, tolerant dump parsing
│ ├── repodb.py local pacman sync database reader
│ ├── query.py extensible query parser (@maintainer, …)
│ ├── search.py fuzzy scoring and ranking engine
│ ├── installer.py clone / review / makepkg / pacman install workflow
│ ├── config.py paths and constants
│ ├── errors.py user-facing error types
│ └── tui/ Textual application, detail view
└── tests/
```
## License
MIT — see [LICENSE](LICENSE).