# profile — to-do list Items marked **[easy]**, **[medium]**, or **[hard]** give a rough effort hint. Items marked **[breaking]** would change existing behaviour and require a version-bump. --- ## Shell / compatibility - [ ] **ZSH compatibility layer** — most functions work already; the remaining blockers are `local -A` (no associative arrays in ZSH without `typeset -A`) and `local -n` namerefs. A thin compatibility shim would open the project to ZSH users. **[hard]** - [ ] **Bash completion** — add a more bash completion directory and write `_profile_upgrade`, `_taz`, `_utaz`, `_meteo`, etc. completions so that `` works on all public functions. **[medium]** --- ## Prompt & theming - [x] **Git branch in prompt** — show the current branch name (with dirty and upstream drift indicators) in the PS1 bar when inside a Git repository, gated by `[prompt]` config keys. **[medium]** - [x] **Virtual-env / conda indicator** — detect `$VIRTUAL_ENV` / `$CONDA_DEFAULT_ENV` and display the active environment in the prompt bar. **[easy]** - [x] **Session context markers** — display lightweight session markers (`ssh`, `tmux`, `screen`) at the end of the prompt bar, gated by `[prompt]` config keys. **[easy]** - [x] **True-colour terminal auto-detection** — query `$COLORTERM` and `$TERM` at load time; automatically fall back from a 24-bit theme to its 16-colour equivalent when the terminal does not support true colour. **[medium]** - [ ] **True-colour variants of other themes** — create `monokai-tc.theme`, `abyss-tc.theme`, etc. using the same `\e[38;2;R;G;Bm` approach as the Solarized themes. **[easy]** _(per theme)_ - [X] **Theme preview command** — add a `theme_preview` (or `profile_theme`) function that renders a colour swatch and a sample prompt line for the currently loaded theme, so users can evaluate themes without reloading the session. **[medium]** - [ ] **`load_theme` — DEFAULTCOL rebuild** — after overriding `DEFAULTFG` and `DEFAULTBG`, automatically recompute `DEFAULTCOL` from the new values instead of requiring the theme file to set it explicitly. **[easy]** --- ## Module improvements ### compress - [ ] **`taz` progress bar** — show a `pv` / `dd`-based progress indicator when compressing large trees, gated behind a `-p` flag. **[medium]** - [ ] **`utaz` integrity check** — run `tar -tOf` / `unzip -t` / `7z t` before extracting and abort if the archive is corrupt. **[easy]** ### filefct - [x] **`findbig` / `findzero` / `finddead` — `fd` integration** — optionally use `fd` instead of `find` when available for faster traversal. **[easy]** - [x] **`file_stats` — human-readable totals** — add `--human` flag to emit sizes in K/M/G instead of bytes. **[easy]** ### info - [X] **`showinfo` fallback** — when neither `neofetch` nor `fastfetch` is installed, print a minimal sysinfo block (hostname, OS, kernel, uptime, CPU, RAM) using pure Bash + `/proc`. **[medium]** ### net - [X] **`dwl` resume support** — pass `-C -` to curl / `--continue-at -` to wget for interrupted downloads; gate behind a `-r` flag. **[easy]** - [ ] **`myextip` multiple providers** — fall back to a secondary URL (configurable via `MYEXTIP_FALLBACK_URL`) when the primary times out. **[easy]** ### processes - [X] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be killed without acting. **[easy]** ### pwd - [ ] **`genpwd` passphrase mode** — add `-w` / `--words N` to generate word-based passphrases (diceware-style) from `/usr/share/dict/words`. **[medium]** ### ssh - [ ] **SSH agent management** — add `ssh_agent_start` / `ssh_agent_stop` helpers that start a persistent `ssh-agent`, add configured keys, and survive re-login via a socket stored in `~/.ssh/agent.env`. **[medium]** - [x] **`rmhost` glob support** — allow `rmhost '*.example.com'` to remove all matching entries in one call. **[easy]** ### updates - [ ] **Automatic update check age** — store a timestamp in `~/.cache/profile_last_check`; skip the network request in `check_updates -q` if the last check was less than `UPDT_CHECK_INTERVAL` hours ago (configurable, default 24). **[medium]** - [ ] **Changelog display** — after a successful `profile_upgrade`, fetch and display `CHANGELOG.md` entries newer than the previously installed version. **[medium]** --- ## Structure - [ ] **Helpers must not stay in the environment (do first)** — internal functions (`_` prefix, `helpers/`) are not part of the user interface, yet 16 of them are `export -f`, so they leak into the environment of every child process. By design they should only exist where they are needed: - stop exporting helpers by default; unset the ones only needed at load time (as `profile.sh` already does for `parse_conf`, `load_alias`, ...); - a helper stays exported only when an exported public function calls it and must work in a child bash (`bash -c`, `find -exec`, `xargs`), which has to be checked and documented one by one (otherwise that public function is no longer exported either, or waits for the stub mechanism below); - add a check (shellcheck-like script or `bats` test) listing exported functions starting with `_`, so none comes back unnoticed. This is the first step: it does not depend on the lazy loading below, which builds on it. **[medium]** - [ ] **Load code on demand (stubs, lazy loading, optional unloading)** — today every module is sourced at startup (about 63 ms, 109 functions) and 80 functions are exported (about 250 KB of environment inherited by every external command, which makes each one about 25 % slower and eats `ARG_MAX`). Replace this by: - *Stubs*: each lazy command is a tiny generated function (`rain() { _lazy rain "$@"; }`), the only thing exported. The stubs come from a command-to-module index, built at upgrade time from a `# provides: ...` header in each module (so `help`, `type` and completion still see every command). - *Lazy loading* (`_try_load`): the first call sources the module and its `helpers/.sh` (and the modules it depends on, declared in the header), then runs the real function (`_exec`). The code stays loaded afterwards. Helpers and implementations are no longer exported, which also removes them from the environment of child shells. - *Optional unloading* (`_free`, e.g. `PROFILE_UNLOAD=1`): after the call, put the stub back instead of unsetting the function. Must be idempotent (Ctrl-C or `return` skip the cleanup), must not free code still referenced by a trap (`_rain_stop`, WINCH handler) or used by a running caller (reference count), and costs about 4 ms per call, so it is not the default. - *Always resident*: `disp`, `conf`, `debug`, `prompt` (and the `DEBUG` timer hook), `lang` shortcuts and `help`. With unloading, state kept across calls (`pwd` pool, current theme, `settrace`) must live in variables that are not freed. Lazy candidates: `compress`, `filefct`, `fun`, `git`, `info`, `net`, `packages`, `processes`, `pwd`, `rain`, `ssh`, `updates`. - *To solve*: `load_conf`/`CONF_*` must stay available at call time; child shells need `MYPATH` and the loader exported to resolve stubs; tracebacks show the loader frames. Do it after the test suite exists, as regressions would be silent. **[hard]** --- ## Infrastructure - [ ] **Test suite** — add a `test/` directory with `bats` (Bash Automated Testing System) unit tests for pure functions (`expandlist`, `genpwd`, `pwdscore`, `isipv4`, `isipv6`, `parse_conf`, `load_theme`, …). Target for CI. **[hard]** - [ ] **CI pipeline** — Gitea Actions (or similar) job that runs `shellcheck` and the `bats` suite on every push. **[medium]** - [ ] **`profile_status` function** — print a diagnostic summary: installed version, active theme, loaded modules, detected Bash version, interactive / login shell flags, and `profile.conf` path. **[easy]** - [ ] **`profile_uninstall` function** — remove the `source` line from `~/.bashrc` / `~/.profile` and optionally delete the install directory, with a dry-run mode. **[medium]** - [ ] **`disp` syslog integration** — add a `DISP_SYSLOG=` config key that additionally pipes E/W messages to `logger`. **[easy]** - [ ] **XDG base-dir support** — honour `$XDG_CONFIG_HOME` as an alternative location for `profile.conf` so users can keep `~` tidy. **[medium]** **[breaking]**