From b3f909e287c815144f38477588d73a8ba2ce59f0 Mon Sep 17 00:00:00 2001 From: fatalerrors Date: Wed, 15 Apr 2026 14:09:34 +0200 Subject: [PATCH] added documentation --- README.md | 366 ++++++++++++++++++++++++++++++--------- doc/CONTRIBUTING.md | 171 ++++++++++++++++++ doc/FAQ.md | 208 ++++++++++++++++++++++ doc/profile.conf.example | 247 ++++++++++++++++++++++++++ doc/todo.md | 121 +++++++++++++ 5 files changed, 1035 insertions(+), 78 deletions(-) create mode 100755 doc/CONTRIBUTING.md create mode 100755 doc/FAQ.md create mode 100755 doc/profile.conf.example create mode 100755 doc/todo.md diff --git a/README.md b/README.md index effd67e..730ffe0 100644 --- a/README.md +++ b/README.md @@ -1,113 +1,323 @@ # profile -This project aims to create an advanced bash profile. It includes some aliases, +This project aims to create an advanced bash profile. It includes aliases, a customized prompt and several functions for different purposes. It's mostly -targeted to system administrator but might satisfy some regular users. +targeted to system administrators but might satisfy some regular users. -## 1. Getting started +## 1. Requirements +profile requires **Bash 4.3 or higher** (for associative arrays and namerefs). +It will refuse to load on older versions and will also refuse to load if the +current shell is not bash. + +## 2. Getting started Download and extract (or use git clone) the profile archive into your home -directory. You will have to modify your ~/.bashrc and/or ~/.profile file to add -at the end (preferably): -``` +directory. You will have to modify your `~/.bashrc` and/or `~/.profile` file to +add at the end (preferably): +```bash source /profile/profile.sh ``` -It's not recommended to load that profile in /etc/profile as the users' .bashrc +You may also set the `PROFILE_PATH` environment variable before sourcing if you +want to override the automatic path detection: +```bash +export PROFILE_PATH=/opt/profile +source /opt/profile/profile.sh +``` + +It's not recommended to load that profile in `/etc/profile` as users' `.bashrc` files might interfere with some aliases and functions defined in profile. -## 2. What's the purpose? -profile is giving access to numerous functions, aliases and to an advanced -prompt. Here is a non-exhaustive list of what we have: -- A bar style prompt with hour, execution time and exit code of the last -command; -- clean: erase after confirmation any backup file, possibly recursively; -- dwl: a curl/wget/fetch download wrapper; -- pkgs: search for the given pattern in the installed packages name; -- expandlist: usefull in scripts, it expand any expression using wildcards into -the corresponding list of file and directories; -- genpwd: generate one or more random secure password; -- gpid: give the list of PID matching the given process name; -- help: display the list of available function and basic use; -- isipv4: tell if the given parameter is a valid IPv4 address; -- isipv6: tell if the given parameter is a valid IPv6 address; -- ku: kill all the processes owned by the given user name or ID; -- mcd: create a directory and immediately move into it; -- meteo: display weather forecast information; -- myextip: get informations about your public IP; -- ppg: look for the given patern in the running processes; -- rain: console screensaver with rain effect; -- rmhost: remove the given host (name or IP) to the list of SSH known host; -- rmspc: in the current directory it replace all the spaces in filenames with a -underscore caracter (or any other given in option); -- setc: set locale on standard C; -- setfr: set locale on French; -- settrace: allow the debugging of any script by showing a backtrace in case of -error; -- setus: set locale on US English; -- showinfo: display basic informations about the host; -- ssr: root ssh login to the given host; -- taz: a universal command to compress files and directories, possibly several -at once; -- utaz: a utility that smartly uncompress many archives at once, creating a -directory only if needed; -- ver: show profile version. +## 3. What's the purpose? +profile gives access to numerous functions, aliases and to an advanced prompt. +All functions are organized into modules under the `profile.d/` directory and +are loaded automatically at startup. -## 3. Configuration -Some functions might have configurable default behaviour. You can create a -profile.conf file to configure those default behaviour. You should have a look -at the doc/profile.conf.example to see the list of available options. The -configuration file is located in the same directory as profile.sh file. +### 3.1. Prompt +A bar-style prompt showing current time, execution time of the last command +(with sub-millisecond precision), and the exit code of the last command. -## 4. Contact and more information -### 4.1. New users -This project is very new in terms of publication, and I have no idea of who will -use it, if any does. If you use (or plan to use) ```profile```, I'll be very -happy if you simply mail me to let me know, especially if you don't plan to -contribute. If you plan to contribute, I'll be twice happier for sure! +### 3.2. Functions reference -### 4.2. Bugs +| Function | Module | Description | +|---|---|---| +| `busy` | fun | Monitor /dev/urandom for a hex pattern — look busy | +| `check_updates` | updates | Check whether a newer profile version is available online | +| `clean` | filefct | Erase backup files in given directories, optionally recursive | +| `disp` | disp | Display formatted info / warning / error / debug messages | +| `dwl` | net | Download a URL using curl, wget, or fetch transparently | +| `expandlist` | filefct | Expand glob expressions into a quoted, separated list | +| `file_stats` | filefct | Display file size statistics for a path | +| `findbig` | filefct | Find the biggest files in the given or current directory | +| `finddead` | filefct | Find dead symbolic links in the given or current directory | +| `findzero` | filefct | Find empty files in the given or current directory | +| `genpwd` | pwd | Generate one or more random secure passwords with configurable constraints | +| `gpid` | processes | Give the list of PIDs matching the given process name(s) | +| `help` | help | Display the list of available functions and basic usage | +| `isipv4` | net | Tell if the given parameter is a valid IPv4 address | +| `isipv6` | net | Tell if the given parameter is a valid IPv6 address | +| `ku` | processes | Kill all processes owned by the given user name or ID | +| `matrix` | rain | Console screensaver with Matrix-style digital rain (binary, kana, ascii charset) | +| `mcd` | filefct | Create a directory and immediately move into it | +| `meteo` | info | Display weather forecast for the configured or given city | +| `myextip` | net | Get information about your public IP address | +| `pkgs` | packages | Search for a pattern in installed package names (dpkg/rpm, supports `-i`) | +| `ppg` | processes | Look for the given pattern in running processes | +| `ppn` | processes | List processes matching an exact command name | +| `ppu` | processes | List processes owned by a specific user | +| `profile_upgrade` | updates | Upgrade profile to the latest version (git pull or archive) | +| `pwdscore` | pwd | Calculate the strength score of a given password | +| `rain` | rain | Console screensaver with falling-rain effect (multiple color themes) | +| `rmhost` | ssh | Remove host (name and IP) from SSH known_hosts; supports `--all-users` as root | +| `rmspc` | filefct | Replace spaces in filenames with underscores (or a custom character) | +| `setc` | lang | Set locale to standard C (POSIX) | +| `setlocale` | lang | Set console locale to any installed locale | +| `settrace` | debug | Activate or deactivate ERR trap to display backtrace on script errors | +| `showinfo` | info | Display welcome banner and system information (figlet + neofetch/fastfetch) | +| `ssr` | ssh | SSH into a server as root, forwarding extra ssh options | +| `taz` | compress | Compress files and directories into a chosen archive format | +| `urlencode` | net | URL-encode a string | +| `utaz` | compress | Smartly uncompress archives (zip, tar.gz/bz2/xz/lz, rar, arj, lha, ace, 7z, zst, cpio, cab, deb, rpm) | +| `ver` | info | Display the installed profile version | + +Locale shortcut functions (`setfr`, `setus`, etc.) are dynamically generated at +startup from the `SET_LOCALE` configuration key (see section 4). + +## 4. Configuration +profile uses an INI-style configuration file (`profile.conf`) located in the +same directory as `profile.sh`. Sections are declared with `[section_name]` and +keys follow `key = value` syntax. Each module calls `load_conf "
"` at +load time, which exports every key in that section as an environment variable. +Unknown keys are silently ignored; all keys are optional — sensible defaults +apply when unset. + +### 4.1. Core sections + +| Section | Purpose | +|---|---| +| `[system]` | Bash history size, pager, and other shell behaviours | +| `[general]` | General-purpose variables (e.g. compilation flags, `MAKEFLAGS`) | +| `[aliases]` | User command aliases, loaded for interactive shells only | + +### 4.2. Module defaults + +Each module exposes its hardcoded defaults as configuration keys. Set a key to +change the default without having to pass flags every time. + +**`[compress]`** — `taz` / `utaz` + +| Key | Default | Description | +|---|---|---| +| `TAZ_DEFAULT_FORMAT` | `tar.gz` | Archive format for `taz` (`tar.gz`, `tar.bz2`, `tar.xz`, `zip`, …) | +| `TAZ_DEFAULT_THREADS` | `0` | Compression threads (0 = auto-detect) | +| `TAZ_DEFAULT_LEVEL` | `6` | Compression level (1–9) | +| `UTAZ_DEFAULT_DELETE` | `0` | Set to `1` to delete the source archive after extraction | +| `UTAZ_DEFAULT_DIR_MODE` | `0` | Set to `1` to always extract into a subdirectory | + +**`[filefct]`** — file utilities + +| Key | Default | Description | +|---|---|---| +| `EXPANDLIST_DEFAULT_SEPARATOR` | ` ` (space) | Separator used by `expandlist` | +| `CLEAN_DEFAULT_RECURSIVE` | `0` | Set to `1` to make `clean` recurse into subdirectories | +| `RMSPC_DEFAULT_CHAR` | `_` | Replacement character used by `rmspc` | +| `FINDBIG_DEFAULT_LIMIT` | `10` | Number of results returned by `findbig` | + +**`[rain]`** — screensavers + +| Key | Default | Description | +|---|---|---| +| `RAIN_DEFAULT_SPEED` | `0.1` | Falling speed for `rain` | +| `RAIN_DEFAULT_COLOR` | `Green` | Colour for `rain` | +| `MATRIX_DEFAULT_SPEED` | `0.05` | Falling speed for `matrix` | +| `MATRIX_DEFAULT_COLOR` | `Green` | Colour for `matrix` | +| `MATRIX_DEFAULT_CHARSET` | `binary` | Character set for `matrix` (`binary`, `kana`, `ascii`) | + +**`[ssh]`** + +| Key | Default | Description | +|---|---|---| +| `SSH_DEFAULT_OPT` | _(empty)_ | Extra options passed to `ssr` (e.g. `-Y` for X forwarding) | + +**`[pwd]`** — password tools + +| Key | Default | Description | +|---|---|---| +| `GENPWD_DEFAULT_LENGTH` | `16` | Generated password length | +| `GENPWD_DEFAULT_OCCURS` | `1` | Number of character class occurrences | +| `GENPWD_DEFAULT_COUNT` | `1` | Number of passwords to generate | +| `GENPWD_DEFAULT_SYMBOLS` | `1` | Include symbols (0/1) | +| `GENPWD_DEFAULT_UPPERCASE` | `1` | Include uppercase letters (0/1) | +| `GENPWD_DEFAULT_LOWERCASE` | `1` | Include lowercase letters (0/1) | +| `GENPWD_DEFAULT_NUMBERS` | `1` | Include digits (0/1) | +| `PWDSCORE_DEFAULT_VERBOSE` | `0` | Set to `1` for detailed scoring output from `pwdscore` | + +**`[fun]`** + +| Key | Default | Description | +|---|---|---| +| `BUSY_DEFAULT_PATTERN` | `[0-9a-f]` | Hex pattern matched by `busy` | +| `BUSY_DEFAULT_DELAY` | `0.1` | Polling delay (seconds) for `busy` | + +**`[info]`** + +| Key | Default | Description | +|---|---|---| +| `METEO_DEFAULT_CITY` | _(empty)_ | Default city for `meteo` when no argument is given | + +**`[net]`** + +| Key | Default | Description | +|---|---|---| +| `DWL_PREFERRED_TOOL` | _(empty)_ | Force `dwl` to use `curl`, `wget`, or `fetch` (auto-detected when unset) | +| `MYEXTIP_DEFAULT_URL` | `https://ip-api.com/json` | API endpoint used by `myextip` | + +**`[packages]`** + +| Key | Default | Description | +|---|---|---| +| `PKGS_DEFAULT_IGNORE_CASE` | `0` | Set to `1` to make `pkgs` case-insensitive by default | + +**`[processes]`** + +| Key | Default | Description | +|---|---|---| +| `PPU_DEFAULT_FORMAT` | `pid,user,comm,args` | `ps` output format used by `ppu` | +| `KU_DEFAULT_SIGNAL` | `TERM` | Default signal sent by `ku` | + +**`[updates]`** + +| Key | Default | Description | +|---|---|---| +| `UPDT_DEFAULT_BRANCH` | `master` | Git branch used for update checks and `profile_upgrade`. Changing this value causes `profile_upgrade` to automatically switch the local checkout to the new branch on the next run and display a warning. | + +### 4.3. Locale shortcuts + +The `[general]` key `SET_LOCALE` accepts a comma-separated list of +`alias:locale` pairs. Each pair generates a function of that name at startup: + +```ini +SET_LOCALE = fr:fr_FR.UTF-8, us:en_US.UTF-8 +``` + +This creates `setfr` and `setus`. Use `setlocale ` to switch to any +installed locale directly. + +### 4.4. Prompt theming + +The prompt appearance is controlled by two mechanisms that are applied in order +(later values win): + +1. **Theme file** — sets a base colour palette. +2. **`[prompt]` section** in `profile.conf` — per-key overrides on top of the theme. + +**Selecting a theme:** + +```ini +[prompt] +PROMPT_THEME = dark # bare name → profile.d/themes/dark.theme +PROMPT_THEME_DIR = ~/.mythemes # optional: custom search directory +``` + +Built-in themes: `default`, `dark`, `light`, `solarized`, `solarized-light`, +`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`. + +**Overriding individual prompt colour slots:** + +```ini +[prompt] +PROMPT_COLOR_USER_FG = $ICyan +PROMPT_COLOR_DIR_FG = $IYellow +``` + +The eleven available `PROMPT_COLOR_*` keys are: + +| Key | Role | +|---|---| +| `PROMPT_COLOR_TIME_FG` / `TIME_BG` | Clock foreground / background | +| `PROMPT_COLOR_BAR_BG` | Main bar background | +| `PROMPT_COLOR_OK_FG` / `OK_MARK` | Exit-code text / checkmark on success | +| `PROMPT_COLOR_ERR_BG` / `ERR_FG` / `ERR_MARK` | Error bar background / text / X mark | +| `PROMPT_COLOR_ROOT_FG` | Username colour when running as root | +| `PROMPT_COLOR_USER_FG` | Username@host colour for normal users | +| `PROMPT_COLOR_DIR_FG` | Working directory colour | + +**Writing a custom theme file:** + +Theme files live in `profile.d/themes/` and use the `.theme` extension. They +are **parsed, not executed** — no shell code runs. Only two value forms are +accepted: + +```ini +# Colour variable reference (resolved from profile.d/disp.sh) +PROMPT_COLOR_DIR_FG = "$ICyan" + +# Raw ANSI escape sequence (single block, 16-colour or 24-bit true-colour) +PROMPT_COLOR_BAR_BG = "\e[48;2;7;54;66m" +``` + +Any unknown key, unsafe value, or shell construct is discarded with a warning. +Theme files may also override the standard colour variables (`Black`, `Blue`, +`On_IBlack`, etc.) to remap the entire terminal palette used by `ls`, `grep`, +and other colour-aware tools. + +True-colour themes (`solarized`, `solarized-light`) require a terminal with +24-bit colour support (Konsole, iTerm2, kitty, Alacritty, Windows Terminal). +Verify support with: +```bash +printf '\e[38;2;38;139;210mTrue colour test\e[0m\n' +``` + +## 5. Contact and more information +### 5.1. New users +If you use (or plan to use) `profile`, I'll be happy if you simply mail me to +let me know, especially if you don't plan to contribute. If you plan to +contribute, I'll be twice happier for sure! + +### 5.2. Bugs **profile** bug tracker is hosted on its Gitea instance. Check the https://git.geoffray-levasseur.org/fatalerrors/profile page. If you find a bug, you can also submit a bug report to the maintainer mail address mentioned at the end of that document. A bug report may contain the command line parameters -where the bug happens, OS details, the module that trigger it, if any, and the -log file containing the error. Cygwin users: please note that bash -implementation in Cygwin triggers regularly bugs on advanced code that triggers -nothing with Linux or BSD. Please do not send synthax error bug repports if you -didn't test the same code in the same conditions using a real Unix. +where the bug happens, OS details, the module that triggered it, if any, and the +log file containing the error. Cygwin users: please note that the bash +implementation in Cygwin regularly triggers bugs on advanced code that works +fine on Linux or BSD. Please do not send syntax error bug reports if you +have not tested the same code under a real Unix environment. -Please check the to-do list before sending any feature request, as it might -have already be requested. +Check the [FAQ](./doc/FAQ.md) and the [to-do list](./doc/todo.md) before +sending any feature request or bug report, as it might already be documented. -### 4.3. How to contribute? +### 5.3. How to contribute? You are free to improve and contribute as you wish. If you have no idea what to do or want some direction, you can check the [to-do list](./doc/todo.md), containing desired future improvements. Make sure you always have the latest development version before starting your work. -It's heavily recommended to use git to obtain the latest copy of profile tree. -Make sure your git configuration is correct in order to contribute. Please -contact me to obtain push authorizations, or, if you want to submit a patch, you -can send it by mail to the maintainer of init.sh. +Read [CONTRIBUTING.md](./doc/CONTRIBUTING.md) for code style conventions, +branch workflow, and how to submit a patch or pull request. -Code written in Python or Perl might be accepted as long as it's not mobilizing -a lot of dependencies (forget big framework). Anything that need the -installation of packages not provided in minimal Debian or CentOS installation -will be probably rejected. +It's heavily recommended to use git to obtain the latest copy of the profile +tree. Make sure your git configuration is correct in order to contribute. +Please contact me to obtain push authorizations, or, if you want to submit a +patch, you can send it by mail to the maintainer of profile. + +Code written in Python or Perl might be accepted as long as it is not +mobilizing a lot of dependencies (forget big frameworks). Anything that +requires installing packages not provided in a minimal Debian or CentOS +installation will probably be rejected. If you want to make a financial contribution, please contact me by mail. -### 4.4. License, website, and maintainer -Everything except configuration files is licensed under BSD-3 license. Please -check license file allong this one. +### 5.4. License, website, and maintainer +Everything except configuration files is licensed under the BSD-3 license. +Please check the license file alongside this one. Please check [https://www.geoffray-levasseur.org/profile](https://www.geoffray-levasseur.org/profile). -Note that this website is still under construction and needs some more care. -You can mail author to fatalerrors \ geoffray-levasseur \ org. +You can mail the author at fatalerrors \ geoffray-levasseur \ org. ----------------------------------------------------------------------------- -Documentation (c) 2021-2022 Geoffray Levasseur. +Documentation (c) 2021-2026 Geoffray Levasseur. -This file is distributed under3-clause BSD license. The complete license +This file is distributed under the 3-clause BSD license. The complete license agreement can be obtained at: https://opensource.org/licenses/BSD-3-Clause diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md new file mode 100755 index 0000000..3fb95bf --- /dev/null +++ b/doc/CONTRIBUTING.md @@ -0,0 +1,171 @@ +# Contributing to profile + +Thank you for your interest in contributing. This document explains how to get +set up, what the conventions are, and how to submit work. + +--- + +## 1. Before you start + +- Check the [to-do list](./todo.md) to see if your idea is already planned. +- Check the [issue tracker](https://git.geoffray-levasseur.org/fatalerrors/profile/issues) + to avoid duplicate work. +- For significant changes, open an issue or contact the maintainer before + writing code — alignment on design saves everyone time. + +--- + +## 2. Getting the source + +A Git clone is mandatory for contributions: + +```bash +git clone https://git.geoffray-levasseur.org/fatalerrors/profile.git +cd profile +``` + +Always work from the **latest commit on `master`** (or the branch you intend +to target). Stale forks cause avoidable merge conflicts. + +--- + +## 3. Development environment + +| Requirement | Minimum version | Notes | +|---|---|---| +| Bash | 4.3 | Namerefs (`local -n`) required | +| shellcheck | any recent | Run before every commit | +| git | any | For contributing patches | +| bats-core | 1.x | Optional — for running the test suite | + +Install shellcheck: +```bash +# Debian / Ubuntu +apt-get install shellcheck + +# Fedora / RHEL +dnf install ShellCheck + +# macOS +brew install shellcheck +``` + +--- + +## 4. Code style + +### General rules +- **Bash only** — no external interpreters in core modules. Python or Perl is + acceptable for completely self-contained, optional utilities that have no + dependencies beyond a minimal Debian or CentOS installation. +- **4-space indentation** — no tabs. +- **`[[ … ]]`** for all conditionals — not `[ … ]`. +- **`(( … ))`** for arithmetic — not `$(( … ))` in conditionals. +- **`local`** for all function-internal variables — avoid polluting the + environment. +- **`printf`** instead of `echo` wherever the format matters. +- **Never `eval`** — use namerefs (`local -n`), `${!varname}` indirection, or + `declare -g` instead. +- **No hardcoded defaults** — wire every configurable value through + `${VAR:-default}` and document the key in `profile.conf` and `README.md §4`. + +### Function conventions +- Public functions **must** be exported: `export -f funcname`. +- Every public function **must** support `-h` / `--help` and print usage to + stdout, returning 0. +- Use `getopt` (not `getopts`) for option parsing — it handles long options and + `--` correctly. +- Follow existing error-return conventions: 0 = success, 1 = usage error, + 2 = bad options, 3 = missing dependency, 4+ = runtime failure. +- Prefix all local helper variables with a short unique prefix (e.g. `_taz_`) + to prevent collisions with caller-scope variables. + +### Module structure +Every new module should follow this pattern: + +```bash +#!/usr/bin/env bash +# + +load_conf "" + +# --- functions --- + +export -f my_function + +# EOF +``` + +Add the `load_conf` call near the top after any variable declarations. + +--- + +## 5. Configuration keys + +When adding a configurable default: + +1. Use `${MY_VAR:-hardcoded_default}` in the function body. +2. Add a commented-out entry with a description to `profile.conf`. +3. Document the key in the matching table in `README.md §4.2`. + +--- + +## 6. Theming + +New theme files go in `profile.d/themes/` with a `.theme` extension. +They are **parsed, not executed** — do not add shell logic. +See the existing themes and `README.md §4.4` for the allowed syntax. + +--- + +## 7. Running shellcheck + +```bash +shellcheck -x profile.sh profile.d/*.sh +``` + +All warnings must be resolved before a patch will be accepted. Accepted +suppression directives (`# shellcheck disable=SCxxxx`) require an inline +comment explaining why the suppression is necessary. + +--- + +## 8. Submitting a contribution + +### Via Git (preferred) +1. Contact the maintainer to obtain push access, or fork on the Gitea instance. +2. Create a branch: `git checkout -b feature/my-feature`. +3. Commit with a clear subject line: `module: short description (≤ 72 chars)`. +4. Push and open a pull request against `master`. + +### Via patch +If you do not have push access: +```bash +git format-patch origin/master +``` +Send the resulting `.patch` file(s) to +`fatalerrors geoffray-levasseur org`. + +### Commit message format +``` +module: imperative short description + +Optional longer explanation of what changed and why. Wrap at 72 characters. +Reference issue numbers if applicable: closes #42. +``` + +--- + +## 9. What will be rejected + +- Code requiring packages not in a minimal Debian or CentOS install. +- Use of `eval`, `source`-based config loading, or other code-injection vectors. +- Changes that break Bash 4.3 compatibility. +- Patches without a passing `shellcheck` run. +- New functions without `--help` support. + +--- + +## 10. Financial contributions + +Contact the maintainer by mail if you wish to make a financial contribution. diff --git a/doc/FAQ.md b/doc/FAQ.md new file mode 100755 index 0000000..d54735c --- /dev/null +++ b/doc/FAQ.md @@ -0,0 +1,208 @@ +# Frequently Asked Questions + +--- + +## Installation & loading + +**Q: profile refuses to load and prints "This profile requires Bash 4.3 or higher."** + +Your system's default shell is an older Bash (common on macOS, which ships +Bash 3.x for licensing reasons). Install a newer Bash: +```bash +# macOS +brew install bash +# then add /opt/homebrew/bin/bash to /etc/shells and chsh +``` +Or point your terminal emulator at the newer binary explicitly. + +--- + +**Q: I sourced `profile.sh` but functions are not available in sub-shells or scripts.** + +All public functions are exported with `export -f`. They are available in +child Bash processes, but **not** in POSIX `sh` sub-shells. Make sure your +scripts start with `#!/usr/bin/env bash`. + +--- + +**Q: I set `PROFILE_PATH` but profile still can't find its modules.** + +`PROFILE_PATH` must be exported *before* you source `profile.sh`: +```bash +export PROFILE_PATH=/opt/profile +source /opt/profile/profile.sh +``` +If set after sourcing, `MYPATH` is already locked in and the variable has +no effect. + +--- + +**Q: Can I load profile system-wide via `/etc/profile`?** + +It is not recommended. User `.bashrc` files frequently set variables that +conflict with the aliases and locale functions defined here, leading to +surprising behaviour. Per-user sourcing from `~/.bashrc` is the supported +method. + +--- + +## Configuration + +**Q: I edited `profile.conf` but my changes have no effect.** + +`profile.conf` is parsed once per shell session at load time. Open a new +terminal (or `exec bash`) to pick up the changes. There is no live-reload. + +--- + +**Q: How do I find out which configuration keys a module supports?** + +Every supported key is documented with a comment in `profile.conf`. +See also `README.md §4.2` for a consolidated table. + +--- + +**Q: A key I set in `profile.conf` is being ignored.** + +Check that: +1. The key is inside the correct `[section]` header. +2. There is no leading space before the section name (`[section]` not + `[ section ]`). +3. The key is not commented out (no leading `#`). +4. The value contains no backticks or `$(…)` — these are stripped by the + parser as a security measure. + +--- + +## Prompt & theming + +**Q: How do I change the prompt theme?** + +Add to `profile.conf`: +```ini +[prompt] +PROMPT_THEME = dark +``` +Built-in names: `default`, `dark`, `light`, `solarized`, `solarized-light`, +`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`. + +--- + +**Q: The solarized or solarized-light theme shows wrong colours.** + +Those themes use 24-bit / true-colour ANSI sequences (`\e[38;2;R;G;Bm`). +Test your terminal: +```bash +printf '\e[38;2;38;139;210mTrue colour test\e[0m\n' +``` +If you see a solid blue word your terminal supports true colour. +If you see garbage or plain text, switch to a 16-colour theme +(`dark`, `default`, etc.) or upgrade your terminal emulator. + +--- + +**Q: I created a custom theme but `load_theme` emits "key not allowed" warnings.** + +Theme files are parsed, not executed. Only `PROMPT_COLOR_*` keys and the +standard colour variable names from `disp.sh` (`Black`, `Blue`, `On_IBlack`, +…) are accepted. Any other key — including custom variables — is rejected. +See `README.md §4.4` for the full list of accepted keys and value forms. + +--- + +**Q: Can a theme file contain shell logic or `$(…)` command substitutions?** + +No, and intentionally so. Theme files are parsed line-by-line; shell +constructs are never evaluated. This is a security boundary — a malicious +theme file cannot execute code. Values must be a colour variable reference +(`$Blue`) or a raw ANSI escape literal (`\e[0;34m`). + +--- + +## Functions + +**Q: `meteo` prints "No city specified" even though I set a default.** + +The key is `METEO_DEFAULT_CITY` (not `DEFAULT_CITY`), and it must be in the +`[info]` section: +```ini +[info] +METEO_DEFAULT_CITY = Paris +``` + +--- + +**Q: `dwl` fails with "no download tool found".** + +`dwl` requires one of `curl`, `wget`, or `fetch` to be installed. +Install curl: +```bash +# Debian / Ubuntu +apt-get install curl + +# Fedora / RHEL +dnf install curl +``` +Or set `DWL_PREFERRED_TOOL` in `[net]` to whichever tool you have. + +--- + +**Q: `pkgs` does not find packages I know are installed.** + +`pkgs` delegates to `dpkg -l` (Debian/Ubuntu) or `rpm -qa` (RHEL/Fedora). +If your distribution uses a different package manager (pacman, apk, brew …) +it is not yet supported. See `doc/todo.md` for the tracking issue. + +--- + +**Q: `profile_upgrade` says "no update available" but I know there is one.** + +`check_updates` compares the content of the remote `version` file against +`$PROFVERSION`. If `UPDT_DEFAULT_BRANCH` in `[updates]` points to a different +branch than your installation, the version files may not match. Check: +```bash +cat "$MYPATH/version" +``` +and make sure `UPDT_DEFAULT_BRANCH` matches the branch you track. + +--- + +## Compatibility + +**Q: Some functions misbehave on macOS / Cygwin.** + +Both environments ship non-GNU userland utilities with different flags and +behaviour. profile is primarily developed and tested on Linux (Debian and +RHEL families). macOS and Cygwin bugs are low priority; patches that add +compatibility without breaking Linux support are welcome. + +--- + +**Q: Can I use profile with ZSH?** + +Not officially. Blockers include `local -A` (ZSH requires `typeset -A`) and +`local -n` namerefs. A compatibility layer is listed in `doc/todo.md` but +has not been implemented yet. + +--- + +## Miscellaneous + +**Q: How do I completely disable profile for one session?** + +```bash +PROFILE_DISABLED=1 bash --norc +``` +Or simply open a shell without sourcing `~/.bashrc` (`bash --norc`). + +--- + +**Q: How do I report a bug?** + +Open an issue on the +[Gitea tracker](https://git.geoffray-levasseur.org/fatalerrors/profile/issues) +or send a mail to `fatalerrors geoffray-levasseur org` with: +- The exact command that triggered the bug +- Your OS and Bash version (`bash --version`) +- The module involved +- Any relevant error output diff --git a/doc/profile.conf.example b/doc/profile.conf.example new file mode 100755 index 0000000..b2c2a82 --- /dev/null +++ b/doc/profile.conf.example @@ -0,0 +1,247 @@ +# profile.conf — example / reference configuration +# Copy this file to the profile installation directory as "profile.conf" +# and uncomment / edit the keys you want to change. +# +# Format: +# [section_name] — starts a section +# key = value — sets a key (whitespace around = is optional) +# # comment — line comment +# +# All keys are optional. Sensible defaults apply when unset. +# Values must not contain backticks or $(…) — those are stripped for security. +# ------------------------------------------------------------------------------ + +# ============================================================================== +[system] +# Bash history settings +HISTSIZE=50000 +HISTFILESIZE=100000 +HISTIGNORE="&:[bf]g:exit" + +# Default pager +PAGER=less + +# Terminal colour capability +TERM=xterm-256color + +# ============================================================================== +[compress] +# taz: Default archive format (-f/--format). +# Supported: lz (default), xz, bz2, gz, lzo, tar, zip, zst +#TAZ_DEFAULT_FORMAT=lz + +# taz: Number of compression threads (0 = auto-detect CPU count). +#TAZ_DEFAULT_THREADS=0 + +# taz: Compression level 1 (fast/large) … 9 (slow/small). +#TAZ_DEFAULT_LEVEL=6 + +# utaz: Delete source archive after successful extraction (0=no, 1=yes). +#UTAZ_DEFAULT_DELETE=0 + +# utaz: Subdirectory creation policy. +# auto — create one only when the archive has multiple top-level entries +# always — always extract into a new subdirectory +# never — always flatten into the current directory +#UTAZ_DEFAULT_DIR_MODE=auto + +# ============================================================================== +[debug] +# (no configurable keys yet) + +# ============================================================================== +[disp] +# Uncomment to disable ANSI colours in profile's own output messages. +#NO_COLOR=1 + +# ============================================================================== +[filefct] +# expandlist: Separator between items (default: space). Use \n for newline. +#EXPANDLIST_DEFAULT_SEPARATOR=" " + +# clean: Recurse into subdirectories by default (0=no, 1=yes). +#CLEAN_DEFAULT_RECURSIVE=0 + +# rmspc: Replacement character for spaces in filenames (default: underscore). +#RMSPC_DEFAULT_CHAR=_ + +# findbig: Number of results to display (default: 10). +#FINDBIG_DEFAULT_LIMIT=10 + +# ============================================================================== +[fun] +# busy: Hex pattern searched in /dev/urandom hexdump. +#BUSY_DEFAULT_PATTERN=ca fe + +# busy: Delay between matched lines in milliseconds (0 = no delay). +#BUSY_DEFAULT_DELAY=0 + +# ============================================================================== +[info] +# meteo: Default city when no argument is given. Leave unset to require an +# explicit city argument every time. +#METEO_DEFAULT_CITY=Paris + +# ============================================================================== +[lang] +# Comma-separated alias:locale pairs. One function is generated per entry. +# Example: SET_LOCALE="fr:fr_FR.UTF-8,us:en_US.UTF-8,es:es_ES.UTF-8" +# creates setfr, setus, setes. +#SET_LOCALE=fr:fr_FR.UTF-8,us:en_US.UTF-8 + +# ============================================================================== +[net] +# dwl: Force a specific download tool (curl, wget, fetch). +# Unset = auto-detect (curl preferred, then wget, then fetch). +#DWL_PREFERRED_TOOL=curl + +# myextip: API endpoint for external IP lookup. +# Alternatives: https://ipinfo.io/json, https://ip-api.com/json/ +#MYEXTIP_DEFAULT_URL=https://ip-api.com/json/ + +# ============================================================================== +[packages] +# pkgs: Case-insensitive search by default (0=no, 1=yes). +#PKGS_DEFAULT_IGNORE_CASE=0 + +# ============================================================================== +[processes] +# ppu: ps output columns (comma-separated ps field names). +#PPU_DEFAULT_FORMAT=pid,user,%cpu,%mem,start,time,command + +# ku: Signal sent when killing a user's processes (without SIG prefix). +#KU_DEFAULT_SIGNAL=TERM + +# ============================================================================== +[prompt] +# Name of the prompt theme to load, or an explicit path to a .theme file. +# Built-in themes: default, dark, light, solarized, solarized-light, +# monokai, monochrome, abyss, plasma, adwaita +# Solarized variants require a terminal with 24-bit true-colour support. +#PROMPT_THEME=default + +# Directory searched for bare theme names. Defaults to profile.d/themes/. +#PROMPT_THEME_DIR=/path/to/my/themes + +# Individual colour overrides — these always win over the loaded theme. +# Values must be colour variable names from disp.sh (e.g. $Blue, $On_IBlack) +# or raw ANSI escape sequences (e.g. \e[0;34m). +# +# Clock segment +#PROMPT_COLOR_TIME_FG=$Blue +#PROMPT_COLOR_TIME_BG=$On_IBlack +# +# Main bar background +#PROMPT_COLOR_BAR_BG=$On_Blue +# +# Exit-code segment — success +#PROMPT_COLOR_OK_FG=$White +#PROMPT_COLOR_OK_MARK=$Green +# +# Exit-code segment — failure +#PROMPT_COLOR_ERR_BG=$On_Red +#PROMPT_COLOR_ERR_FG=$White +#PROMPT_COLOR_ERR_MARK=$BYellow +# +# User / host +#PROMPT_COLOR_ROOT_FG=$Red +#PROMPT_COLOR_USER_FG=$Green +# +# Working directory +#PROMPT_COLOR_DIR_FG=$ICyan + +# ============================================================================== +[pwd] +# genpwd: Default password length. +#GENPWD_DEFAULT_LENGTH=16 + +# genpwd: Maximum occurrences of any single character. +#GENPWD_DEFAULT_OCCURS=2 + +# genpwd: Number of passwords generated per invocation. +#GENPWD_DEFAULT_COUNT=1 + +# genpwd: Include symbols (1=yes, 0=no). +#GENPWD_DEFAULT_SYMBOLS=1 + +# genpwd: Include uppercase letters (1=yes, 0=no). +#GENPWD_DEFAULT_UPPERCASE=1 + +# genpwd: Include lowercase letters (1=yes, 0=no). +#GENPWD_DEFAULT_LOWERCASE=1 + +# genpwd: Include digits (1=yes, 0=no). +#GENPWD_DEFAULT_NUMBERS=1 + +# pwdscore: Show verbose breakdown by default (1=yes, 0=no). +#PWDSCORE_DEFAULT_VERBOSE=0 + +# ============================================================================== +[rain] +# rain: Falling speed — integer/100 gives seconds (5 → 0.05 s). +# Values < 1 are used as raw seconds. +#RAIN_DEFAULT_SPEED=5 + +# rain: Colour theme. Supported: white (default), green, blue, red, yellow, cyan +#RAIN_DEFAULT_COLOR=white + +# matrix: Falling speed. +#MATRIX_DEFAULT_SPEED=3.5 + +# matrix: Colour theme. Supported: green (default), blue, red, yellow, cyan, white +#MATRIX_DEFAULT_COLOR=green + +# matrix: Character set. Supported: binary (default), kana, ascii +#MATRIX_DEFAULT_CHARSET=binary + +# ============================================================================== +[ssh] +# ssr: Default SSH options prepended to every ssr call. +# Examples: +# SSH_DEFAULT_OPT=-Y # X11 forwarding +# SSH_DEFAULT_OPT=-Y -o StrictHostKeyChecking=accept-new +# SSH_DEFAULT_OPT= # no default options +#SSH_DEFAULT_OPT=-Y + +# ============================================================================== +[updates] +# Git branch used for update checks and profile_upgrade. +# Changing this causes profile_upgrade to automatically switch the local +# checkout to the new branch on the next run and display a warning. +#UPDT_DEFAULT_BRANCH=master + +# ============================================================================== +[general] +# General-purpose section — set any environment variable you need globally. +# Good place for compilation flags, personal PATH additions, etc. +#CFLAGS=-O2 -pipe -march=native +#CXXFLAGS=$CFLAGS +#MAKEFLAGS=-j4 +#PKGSOURCES=/usr/local/src + +# ============================================================================== +[aliases] +# Command aliases loaded for interactive shells only. +# The value is the full command string; the key becomes the alias name. +# The base command must be executable; if not, the alias is silently skipped. +# +# ls +ll=ls -laFh --color=auto +la=ls -Ah --color=auto +l=ls -CF --color=auto +ls=ls --color=auto +# +# grep +grep=grep --color=auto +egrep=egrep --color=auto +fgrep=fgrep --color=auto +# +# disk usage +df=df -H +du=du -ch +# +# make shortcuts +#mk=make +#mkin=make install + +# End of profile.conf.example diff --git a/doc/todo.md b/doc/todo.md new file mode 100755 index 0000000..84959c6 --- /dev/null +++ b/doc/todo.md @@ -0,0 +1,121 @@ +# 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 `profile.d/completion/` directory and write + `_profile_upgrade`, `_taz`, `_utaz`, `_meteo`, etc. completions so that + `` works on all public functions. **[medium]** +- [ ] **`shellcheck` clean pass** — run `shellcheck -x profile.sh profile.d/*.sh` + and address every remaining warning (currently a handful of SC2034 and SC2086 + items). Integrate as a pre-commit hook. **[easy]** + +--- + +## Prompt & theming + +- [ ] **Git branch in prompt** — show the current branch name (and dirty + indicator) in the PS1 bar when inside a Git repository. Should be + gated behind a `[prompt]` config key so it can be disabled. **[medium]** +- [ ] **Virtual-env / conda indicator** — detect `$VIRTUAL_ENV` / `$CONDA_DEFAULT_ENV` + and display the name in the prompt bar. **[easy]** +- [ ] **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)_ +- [ ] **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 +- [ ] **`findbig` / `findzero` / `finddead` — `fd` integration** — optionally + use `fd` instead of `find` when available for faster traversal. **[easy]** +- [ ] **`file_stats` — human-readable totals** — add `--human` flag to emit + sizes in K/M/G instead of bytes. **[easy]** + +### info +- [ ] **`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 +- [ ] **`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]** + +### packages +- [ ] **Additional backends** — add support for `pacman` (Arch), `apk` (Alpine), + `xbps-query` (Void), and `brew` (macOS). **[medium]** + +### processes +- [ ] **`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]** +- [ ] **`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]** + +--- + +## 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=1` 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]**