5 Commits

Author SHA1 Message Date
fatalerrors
bc0a592fa1 version bump 2026-04-15 14:24:03 +02:00
fatalerrors
b3f909e287 added documentation 2026-04-15 14:09:34 +02:00
fatalerrors
89e20993da allow to chose upgrade branch 2026-04-15 13:44:44 +02:00
fatalerrors
9a006883b8 make defaults configurable 2026-04-15 13:38:08 +02:00
fatalerrors
85f02f4498 themable prompt and some proposed themes 2026-04-15 13:35:33 +02:00
31 changed files with 2299 additions and 277 deletions

379
README.md
View File

@@ -1,113 +1,336 @@
# profile # 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 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 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 directory. You will have to modify your `~/.bashrc` and/or `~/.profile` file to
at the end (preferably): add at the end (preferably):
``` ```bash
source <installpath>/profile/profile.sh source <installpath>/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. files might interfere with some aliases and functions defined in profile.
## 2. What's the purpose? ### 2.1. Initial configuration
profile is giving access to numerous functions, aliases and to an advanced Copy the example configuration file and customise it to your needs:
prompt. Here is a non-exhaustive list of what we have: ```bash
- A bar style prompt with hour, execution time and exit code of the last cp <installpath>/profile/doc/profile.conf.example <installpath>/profile/profile.conf
command; ```
- clean: erase after confirmation any backup file, possibly recursively; `profile.conf` is git-ignored so your personal settings will never be
- dwl: a curl/wget/fetch download wrapper; accidentally committed. All keys are optional — sensible defaults apply when
- pkgs: search for the given pattern in the installed packages name; unset. See [section 4](#4-configuration) for the full reference.
- 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. Configuration ## 3. What's the purpose?
Some functions might have configurable default behaviour. You can create a profile gives access to numerous functions, aliases and to an advanced prompt.
profile.conf file to configure those default behaviour. You should have a look All functions are organized into modules under the `profile.d/` directory and
at the doc/profile.conf.example to see the list of available options. The are loaded automatically at startup.
configuration file is located in the same directory as profile.sh file.
## 4. Contact and more information ### 3.1. Prompt
### 4.1. New users A bar-style prompt showing current time, execution time of the last command
This project is very new in terms of publication, and I have no idea of who will (with sub-millisecond precision), and the exit code of the last command.
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!
### 4.2. Bugs ### 3.2. Functions reference
| 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 "<section>"` 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.
`profile.conf` is listed in `.gitignore` so personal values (API keys, cities,
compiler flags, …) are never accidentally staged. Start from the annotated
template at `doc/profile.conf.example` (see [section 2.1](#21-initial-configuration)).
### 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 (19) |
| `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 <locale>` 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 **profile** bug tracker is hosted on its Gitea instance. Check the
https://git.geoffray-levasseur.org/fatalerrors/profile page. If you find a bug, 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 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 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 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 bash log file containing the error. Cygwin users: please note that the bash
implementation in Cygwin triggers regularly bugs on advanced code that triggers implementation in Cygwin regularly triggers bugs on advanced code that works
nothing with Linux or BSD. Please do not send synthax error bug repports if you fine on Linux or BSD. Please do not send syntax error bug reports if you
didn't test the same code in the same conditions using a real Unix. 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 Check the [FAQ](./doc/FAQ.md) and the [to-do list](./doc/todo.md) before
have already be requested. 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 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), 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 containing desired future improvements. Make sure you always have the latest
development version before starting your work. development version before starting your work.
It's heavily recommended to use git to obtain the latest copy of profile tree. Read [CONTRIBUTING.md](./doc/CONTRIBUTING.md) for code style conventions,
Make sure your git configuration is correct in order to contribute. Please branch workflow, and how to submit a patch or pull request.
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.
Code written in Python or Perl might be accepted as long as it's not mobilizing It's heavily recommended to use git to obtain the latest copy of the profile
a lot of dependencies (forget big framework). Anything that need the tree. Make sure your git configuration is correct in order to contribute.
installation of packages not provided in minimal Debian or CentOS installation Please contact me to obtain push authorizations, or, if you want to submit a
will be probably rejected. 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. If you want to make a financial contribution, please contact me by mail.
### 4.4. License, website, and maintainer ### 5.4. License, website, and maintainer
Everything except configuration files is licensed under BSD-3 license. Please Everything except configuration files is licensed under the BSD-3 license.
check license file allong this one. Please check the license file alongside this one.
Please check [https://www.geoffray-levasseur.org/profile](https://www.geoffray-levasseur.org/profile). 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 \<at\> geoffray-levasseur \<dot\> org. You can mail the author at fatalerrors \<at\> geoffray-levasseur \<dot\> 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 agreement can be obtained at: https://opensource.org/licenses/BSD-3-Clause

71
doc/CHANGELOG.md Executable file
View File

@@ -0,0 +1,71 @@
# Changelog
All notable changes to this project will be documented in this file.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
---
## [3.99.1-4_rc_1] — 2026
### Added
- **Theming system** — `load_theme` in `profile.d/prompt.sh` loads `.theme`
files from `profile.d/themes/` (or a custom directory set via
`PROMPT_THEME_DIR`). Theme files are **parsed, not executed** — no shell code
ever runs from a theme.
- **Built-in themes** — `default`, `dark`, `light`, `solarized` (24-bit
true-colour), `solarized-light` (24-bit), `monokai`, `monochrome`, `abyss`,
`plasma`, `adwaita`.
- **`[prompt]` section** — `PROMPT_THEME` and `PROMPT_THEME_DIR` keys to select
a theme; eleven `PROMPT_COLOR_*` keys for per-key overrides in `profile.conf`.
- **Standard colour variables as theme keys** — theme files may also override
the `disp.sh` colour variables (`Black`, `Blue`, `On_IBlack`, …) to remap the
terminal palette used by `ls`, `grep`, and colour-aware tools.
- **Module configuration defaults** — all modules now expose their hardcoded
defaults as `profile.conf` keys: `TAZ_*`, `UTAZ_*`, `EXPANDLIST_*`,
`CLEAN_*`, `RMSPC_*`, `FINDBIG_*`, `RAIN_*`, `MATRIX_*`, `SSH_DEFAULT_OPT`,
`GENPWD_*`, `PWDSCORE_*`, `BUSY_*`, `METEO_DEFAULT_CITY`, `DWL_*`,
`MYEXTIP_*`, `PKGS_*`, `PPU_*`, `KU_*`, `UPDT_DEFAULT_BRANCH`.
- **`UPDT_DEFAULT_BRANCH`** — configures the git branch used by `check_updates`
and `profile_upgrade`. Changing the key causes `profile_upgrade` to
automatically switch the local checkout to the new branch and display a
warning.
- **`doc/` directory** — `CONTRIBUTING.md`, `FAQ.md`, `profile.conf.example`
(annotated template), `todo.md`.
- **`.gitignore`** — `profile.conf` is now git-ignored so personal settings are
never accidentally staged.
### Changed
- README §2 now explains how to create `profile.conf` from
`doc/profile.conf.example` (new section 2.1 "Initial configuration").
- README §4 updated with full module-defaults tables, theming reference, and a
note about `profile.conf` being git-ignored.
- Theme values no longer carry the `export` keyword (they are not shell
variables, only data).
### Security
- `load_theme` uses a strict allowlist (no `eval`, no sourcing). Only
`PROMPT_COLOR_*` keys and known `disp.sh` colour variable names are accepted.
Values must match `\$[A-Za-z_][A-Za-z0-9_]*` or `\\e\[[0-9;]*m`; any other
value is discarded with a warning.
---
---
> **Note:** Versions prior to `3.95.x-4_beta` did not maintain a formal
> changelog. The full history of earlier changes is available through the git
> log (`git log --oneline`).
## [3.95.3-4_beta_3] — 2024
### Added
- Initial public release candidate series.
- Core modules: `compress`, `disp`, `filefct`, `fun`, `help`, `info`, `lang`,
`net`, `packages`, `processes`, `prompt`, `pwd`, `rain`, `ssh`, `updates`.
- Bar-style prompt with time, command duration, and exit code.
- `taz` / `utaz` archive helpers.
- `genpwd` / `pwdscore` password tools.
- `matrix` / `rain` screensavers.
- `profile_upgrade` with git and archive download support.

171
doc/CONTRIBUTING.md Executable file
View File

@@ -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
# <copyright block identical to existing modules>
load_conf "<module_name>"
# --- 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 <at> geoffray-levasseur <dot> 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.

208
doc/FAQ.md Executable file
View File

@@ -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 <at> geoffray-levasseur <dot> org` with:
- The exact command that triggered the bug
- Your OS and Bash version (`bash --version`)
- The module involved
- Any relevant error output

247
doc/profile.conf.example Executable file
View File

@@ -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

274
doc/profile.conf.fatalerrors Executable file
View File

@@ -0,0 +1,274 @@
[system]
# System section is used to set Bash behavior and other system related
# variables, such as the default pager, the terminal type, etc.
# Set bash history
HISTSIZE=50000
HISTIGNORE="&:[bf]g:exit"
# Set default pager
PAGER=less
# Set terminal colors behavior
TERM=xterm-256color
[compress]
# Section used by compress.sh (taz and utaz functions).
# taz: Default archive format when -f/--format is not specified.
# Supported values: lz (default), xz, bz2, gz, lzo, tar
#TAZ_DEFAULT_FORMAT=lz
# taz: Default number of compression threads when -p/--parallel is not specified.
# Set to the number of CPU cores to use parallel compression where supported.
#TAZ_DEFAULT_THREADS=1
# taz: Default compression level when none is given (1=fast/big .. 9=slow/small).
#TAZ_DEFAULT_LEVEL=6
# utaz: Delete source archives after successful extraction (0=no, 1=yes).
#UTAZ_DEFAULT_DELETE=0
# utaz: Default directory creation mode when neither --create-dir nor --no-dir is given.
# Supported values:
# auto (default) — create a subdirectory only when the archive contains
# multiple top-level entries or a bare file
# always — always extract into a new subdirectory
# never — always flatten extraction into the current directory
#UTAZ_DEFAULT_DIR_MODE=auto
[debug]
# Section used by debug.sh (nothing yet)
[disp]
# Section used by disp.sh
# Set to any value to disable colors in internal profile output (not controling binary output)
# NO_COLOR=1
[filefct]
# Section used by filefct.sh
# expandlist: Default output separator between items (default: space).
# Use \n for newline, or any other character/string.
#EXPANDLIST_DEFAULT_SEPARATOR=" "
# clean: Enable recursive mode by default (0=no, 1=yes).
#CLEAN_DEFAULT_RECURSIVE=0
# rmspc: Default character used to replace spaces in filenames (default: underscore).
# Set to empty to concatenate words without separator (equivalent to --subst-char with no value).
#RMSPC_DEFAULT_CHAR=_
# findbig: Default number of results to return (default: 10).
#FINDBIG_DEFAULT_LIMIT=10
[fun]
# Section used by fun.sh (busy function).
# busy: Default hex pattern to search for in /dev/urandom hexdump (default: "ca fe").
#BUSY_DEFAULT_PATTERN=ca fe
# busy: Default delay between matched lines in milliseconds (default: 0 = no delay).
#BUSY_DEFAULT_DELAY=0
[info]
# Section used by info.sh
# meteo: Default city used when no city argument is given.
# Unset or empty disables the fallback and requires an explicit city argument.
METEO_DEFAULT_CITY="Toulouse"
[lang]
# Section used by lang.sh
# List of locale shortcuts to build, in the form "shortcut:locale,...".
# Generate a function setXX for each shortcut defined.
SET_LOCALE="fr:fr_FR.UTF-8,us:en_US.UTF-8"
[net]
# Section used by net.sh (dwl, myextip functions).
# dwl: Force a specific download tool instead of auto-detecting (curl → wget → fetch).
# Supported values: curl, wget, fetch. Unset uses auto-detection (default).
#DWL_PREFERRED_TOOL=curl
# myextip: API endpoint URL used to retrieve external IP information.
# Default: https://ip-api.com/json/
# Compatible alternatives: https://ipinfo.io/json, https://ip-api.com/json/
#MYEXTIP_DEFAULT_URL=https://ip-api.com/json/
[packages]
# Section used by packages.sh
# pkgs: Enable case-insensitive search by default (1=yes, 0=no; default: 0).
#PKGS_DEFAULT_IGNORE_CASE=0
[processes]
# Section used by processes.sh
# ppu: Output columns passed to ps -o when listing processes for a user.
# Comma-separated list of ps field names. Default: pid,user,%cpu,%mem,start,time,command
#PPU_DEFAULT_FORMAT=pid,user,%cpu,%mem,start,time,command
# ku: Signal sent to processes when killing a user's session (default: TERM).
# Use signal names without the SIG prefix (e.g. TERM, KILL, HUP).
#KU_DEFAULT_SIGNAL=TERM
[prompt]
# Section used by prompt.sh
# Name of the theme to load, or an explicit path to a .theme file.
# Bare names are resolved as $PROMPT_THEME_DIR/<name>.theme.
# When unset, no theme is loaded and the hardcoded fallback colours are used.
#PROMPT_THEME=default
# Directory that contains .theme files. Defaults to profile.d/themes/ inside
# the profile installation directory.
#PROMPT_THEME_DIR=/path/to/themes
# Individual colour overrides. These always win over the loaded theme.
# Values must be valid ANSI escape sequences as exported by disp.sh, e.g.:
# \e[0;34m (Blue) \e[42m (On_Green) \e[1;32m (BGreen)
# All keys listed below correspond to variables exported by disp.sh.
# Clock segment
#PROMPT_COLOR_TIME_FG=$Blue
#PROMPT_COLOR_TIME_BG=$On_IBlack
# Main bar background (success and info)
#PROMPT_COLOR_BAR_BG=$On_Blue
# Exit-code segment — success state
#PROMPT_COLOR_OK_FG=$White
#PROMPT_COLOR_OK_MARK=$Green
# Exit-code segment — failure state
#PROMPT_COLOR_ERR_BG=$On_Red
#PROMPT_COLOR_ERR_FG=$White
#PROMPT_COLOR_ERR_MARK=$BYellow
# User/host colours
#PROMPT_COLOR_ROOT_FG=$Red
#PROMPT_COLOR_USER_FG=$Green
# Working directory
#PROMPT_COLOR_DIR_FG=$ICyan
[pwd]
# Section used by pwd.sh (genpwd and pwdscore functions).
# genpwd: Default password length (default: 16).
#GENPWD_DEFAULT_LENGTH=16
# genpwd: Maximum occurrences of any single character (default: 2).
#GENPWD_DEFAULT_OCCURS=2
# genpwd: Number of passwords generated when no count argument is given (default: 1).
#GENPWD_DEFAULT_COUNT=1
# genpwd: Include symbols in the character pool (1=yes, 0=no; default: 1).
#GENPWD_DEFAULT_SYMBOLS=1
# genpwd: Include uppercase letters in the character pool (1=yes, 0=no; default: 1).
#GENPWD_DEFAULT_UPPERCASE=1
# genpwd: Include lowercase letters in the character pool (1=yes, 0=no; default: 1).
#GENPWD_DEFAULT_LOWERCASE=1
# genpwd: Include digits in the character pool (1=yes, 0=no; default: 1).
#GENPWD_DEFAULT_NUMBERS=1
# pwdscore: Show verbose breakdown by default (1=yes, 0=no; default: 0).
#PWDSCORE_DEFAULT_VERBOSE=0
[rain]
# Section used by rain.sh (rain and matrix functions).
# rain: Default speed value, using the /100 scale (5 => 0.050s, 10 => 0.100s).
# Values < 1 are interpreted as raw seconds.
#RAIN_DEFAULT_SPEED=5
# rain: Default color theme.
# Supported values: white (default), green, blue, red, yellow, cyan
#RAIN_DEFAULT_COLOR=white
# matrix: Default speed value, using the /100 scale (3.5 => 0.035s).
#MATRIX_DEFAULT_SPEED=3.5
# matrix: Default color theme.
# Supported values: green (default), blue, red, yellow, cyan, white
#MATRIX_DEFAULT_COLOR=green
# matrix: Default character set.
# Supported values: binary (default), kana, ascii
MATRIX_DEFAULT_CHARSET=kana
[ssh]
# Section used by ssh.sh
# ssr: Default SSH options prepended to every ssr invocation.
# Options are word-split, so space-separated flags are supported.
# The default behaviour without this key is equivalent to: SSH_DEFAULT_OPT=-Y
# Set to an empty value to pass no default options.
# Examples:
# SSH_DEFAULT_OPT=-Y # X11 forwarding (original default)
# SSH_DEFAULT_OPT=-Y -o StrictHostKeyChecking=accept-new
# SSH_DEFAULT_OPT= # no default options
#SSH_DEFAULT_OPT=-Y
[updates]
# Section used by updates.sh
#
# UPDT_DEFAULT_BRANCH — Git branch used for update checks and upgrades.
# Defaults to 'master' when unset. Changing this value will cause
# profile_upgrade to automatically switch the local checkout to the new
# branch on the next upgrade and display a warning.
#UPDT_DEFAULT_BRANCH=master
[general]
# General section allow to set any variable that can be used by the user.
# It is also a good place to set freely global variables for personal use.
# Set some compiling values
CFLAGS="-O2 -pipe -march=native"
CXXFLAGS="$CFLAGS"
MAKEFLAGS='-j12'
PKGSOURCES='/share/src/archives'
[aliases]
# Aliases section is used to set user aliases, it is loaded only for
# interactive shells.
# Various ls aliases
ll='ls -laFh --color=auto'
la='ls -Ah --color=auto'
l='ls -CF --color=auto'
ls='ls --color=auto'
# Add color to grep output
grep='grep --color=auto'
egrep='egrep --color=auto'
fgrep='fgrep --color=auto'
# Quick find alias
qfind="find . -name "
# Some alias for compiling
mk='make'
mkck='make check'
mkin='make install'
mkdin='make DESTDIR=$PWD/dest-install install'
# ssh alias with X11 forwarding, without right restriction
ssh='ssh -Y'
# Resume mode for wget
wget='wget -c' # resume mode by default
# Human readable by default
df='df -H'
du='du -ch'
sdu='du -sk ./* | sort -n'
hdu='du -hs ./* | sort -H'
# Readable dmesg timestamps
dmesg='dmesg -T'
# End of profile.conf

121
doc/todo.md Executable file
View File

@@ -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
`<Tab>` 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]**

View File

@@ -1,110 +0,0 @@
[system]
# System section is used to set Bash behavior and other system related
# variables, such as the default pager, the terminal type, etc.
# Set bash history
HISTSIZE=50000
HISTIGNORE="&:[bf]g:exit"
# Set default pager
PAGER=less
# Set terminal colors behavior
TERM=xterm-256color
[compress]
# Section used by compress.sh
[debug]
# Section used by debug.sh
[disp]
# Section used by disp.sh
# Set to any value to disable colors in internal profile output (not controling binary output)
# NO_COLOR=1
[filefct]
# Section used by filefct.sh
[fun]
# Section used by fun.sh
[info]
# Section used by info.sh
# Default city for weather forcast and local news
DEFAULT_CITY="Toulouse"
[lang]
# Section used by lang.sh
# List of locale shortcuts to build, in the form "shortcut:locale,...".
# Generate a function setXX for each shortcut defined.
SET_LOCALE="fr:fr_FR.UTF-8,us:en_US.UTF-8"
[net]
# Section used by net.sh
[packages]
# Section used by packages.sh
[prompt]
# Section used by prompt.sh
[pwd]
# Section used by pwd.sh
[rain]
# Section used by rain.sh
[ssh]
# Section used by ssh.sh
[updates]
# Section used by updates.sh
[general]
# General section allow to set any variable that can be used by the user.
# It is also a good place to set freely global variables for personal use.
# Set some compiling values
CFLAGS="-O2 -pipe -march=native"
CXXFLAGS="$CFLAGS"
MAKEFLAGS='-j12'
PKGSOURCES='/share/src/archives'
[aliases]
# Aliases section is used to set user aliases, it is loaded only for
# interactive shells.
# Various ls aliases
ll='ls -laFh --color=auto'
la='ls -Ah --color=auto'
l='ls -CF --color=auto'
ls='ls --color=auto'
# Add color to grep output
grep='grep --color=auto'
egrep='egrep --color=auto'
fgrep='fgrep --color=auto'
# Quick find alias
qfind="find . -name "
# Some alias for compiling
mk='make'
mkck='make check'
mkin='make install'
mkdin='make DESTDIR=$PWD/dest-install install'
# ssh alias with X11 forwarding, without right restriction
ssh='ssh -Y'
# Resume mode for wget
wget='wget -c' # resume mode by default
# Human readable by default
df='df -H'
du='du -ch'
sdu='du -sk ./* | sort -n'
hdu='du -hs ./* | sort -H'
# Readable dmesg timestamps
dmesg='dmesg -T'
# End of profile.conf

View File

@@ -204,6 +204,15 @@ utaz()
local FILES=("$@") local FILES=("$@")
[[ ${#FILES[@]} -eq 0 ]] && FILES=(".") [[ ${#FILES[@]} -eq 0 ]] && FILES=(".")
# Apply defaults from [compress] configuration if not overridden by flags
[[ -z ${willrm+x} ]] && [[ ${UTAZ_DEFAULT_DELETE:-0} -eq 1 ]] && willrm=1
if [[ -z ${createdir+x} && -z ${nodir+x} ]]; then
case "${UTAZ_DEFAULT_DIR_MODE:-auto}" in
always) createdir=1 ;;
never) nodir=1 ;;
esac
fi
[[ -n ${createdir} && -n ${nodir} ]] && \ [[ -n ${createdir} && -n ${nodir} ]] && \
disp E "The --create-dir and --no-dir options are mutually exclusive." disp E "The --create-dir and --no-dir options are mutually exclusive."
@@ -565,9 +574,9 @@ taz()
local FILES=("$@") local FILES=("$@")
[[ ${#FILES[@]} -eq 0 ]] && FILES=(".") [[ ${#FILES[@]} -eq 0 ]] && FILES=(".")
[[ ! $compform ]] && compform=lz # safe and efficient (unless data are already compressed) [[ ! $compform ]] && compform=${TAZ_DEFAULT_FORMAT:-lz}
[[ ! $nproc ]] && nproc=1 [[ ! $nproc ]] && nproc=${TAZ_DEFAULT_THREADS:-1}
[[ ! $complevel ]] && complevel=6 [[ ! $complevel ]] && complevel=${TAZ_DEFAULT_LEVEL:-6}
[[ $verbose -gt 1 && $quiet -gt 1 ]] && [[ $verbose -gt 1 && $quiet -gt 1 ]] &&
disp E "The --verbose and --quiet options can't be used together." disp E "The --verbose and --quiet options can't be used together."
@@ -619,4 +628,6 @@ export -f taz
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "compress"
# EOF # EOF

View File

@@ -39,7 +39,7 @@
# Usage: expandlist [options] <item1 [item2 ... itemN]> # Usage: expandlist [options] <item1 [item2 ... itemN]>
expandlist() expandlist()
{ {
local separator=" " local separator="${EXPANDLIST_DEFAULT_SEPARATOR:- }"
local PARSED local PARSED
PARSED=$(getopt -o hs:n --long help,separator:,newline -n 'expandlist' -- "$@") PARSED=$(getopt -o hs:n --long help,separator:,newline -n 'expandlist' -- "$@")
@@ -122,7 +122,7 @@ export -f expandlist
# -s, --shell: do nothing and display what will be executed # -s, --shell: do nothing and display what will be executed
clean() clean()
{ {
local recursive=0 force=0 outshell=0 local recursive=${CLEAN_DEFAULT_RECURSIVE:-0} force=0 outshell=0
# Define short and long options # Define short and long options
local PARSED local PARSED
@@ -236,7 +236,7 @@ export -f mcd
rmspc() rmspc()
{ {
local recurs=0 verb=0 shell=0 local recurs=0 verb=0 shell=0
local substchar="_" substchar_set=0 local substchar="${RMSPC_DEFAULT_CHAR:-_}" substchar_set=0
local mvopt=() local mvopt=()
local PARSED local PARSED
@@ -574,7 +574,7 @@ export -f file_stats
# -l : limit : number of files to return (default is 10) # -l : limit : number of files to return (default is 10)
findbig() findbig()
{ {
local details=0 limit=10 one_fs=0 local details=0 limit=${FINDBIG_DEFAULT_LIMIT:-10} one_fs=0
local PARSED local PARSED
PARSED=$(getopt -o hdl:x --long help,details,limit:,one-fs -n 'findbig' -- "$@") PARSED=$(getopt -o hdl:x --long help,details,limit:,one-fs -n 'findbig' -- "$@")
@@ -792,4 +792,6 @@ export -f finddead
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "filefct"
# EOF # EOF

View File

@@ -42,7 +42,7 @@
# pattern : the string to search for in the hexdump output (default is "ca fe") # pattern : the string to search for in the hexdump output (default is "ca fe")
busy() busy()
{ {
local pattern="ca fe" delay_ms=0 local pattern="${BUSY_DEFAULT_PATTERN:-ca fe}" delay_ms="${BUSY_DEFAULT_DELAY:-0}"
local PARSED local PARSED
# Short: h, p:, d: # Short: h, p:, d:
@@ -109,4 +109,6 @@ busy()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "fun"
# EOF # EOF

View File

@@ -108,7 +108,12 @@ meteo()
local cities=("$@") local cities=("$@")
local city="" encoded="" local city="" encoded=""
[[ $# -eq 0 ]] && cities=("$DEFAULT_CITY") [[ $# -eq 0 ]] && cities=("${METEO_DEFAULT_CITY:-}")
if [[ ${#cities[@]} -eq 0 || -z "${cities[0]}" ]]; then
disp E "No city given and METEO_DEFAULT_CITY is not set. Use 'meteo <city>'."
return 1
fi
for city in "${cities[@]}"; do for city in "${cities[@]}"; do
encoded=$(urlencode "$city") encoded=$(urlencode "$city")

View File

@@ -67,16 +67,38 @@ dwl()
local url="$1" local url="$1"
local output="$2" local output="$2"
if command -v curl >/dev/null 2>&1; then # Honour preferred tool from configuration; fall back to auto-detection.
[ -z "$output" ] && curl -sL "$url" || curl -sL -o "$output" "$url" local preferred="${DWL_PREFERRED_TOOL:-}"
_try_curl() { [ -z "$output" ] && curl -sL "$url" || curl -sL -o "$output" "$url"; }
_try_wget() { [ -z "$output" ] && wget -qO- "$url" || wget -q -O "$output" "$url"; }
_try_fetch() { [ -z "$output" ] && fetch -o - "$url" || fetch -o "$output" "$url"; }
if [[ -n "$preferred" ]]; then
command -v "$preferred" >/dev/null 2>&1 || {
echo "Error: preferred download tool '$preferred' is not installed." >&2
return 1
}
case "$preferred" in
curl) _try_curl ;;
wget) _try_wget ;;
fetch) _try_fetch ;;
*)
echo "Error: DWL_PREFERRED_TOOL '$preferred' is not supported (use curl, wget or fetch)." >&2
return 1
;;
esac
elif command -v curl >/dev/null 2>&1; then
_try_curl
elif command -v wget >/dev/null 2>&1; then elif command -v wget >/dev/null 2>&1; then
[ -z "$output" ] && wget -qO- "$url" || wget -q -O "$output" "$url" _try_wget
elif command -v fetch >/dev/null 2>&1; then elif command -v fetch >/dev/null 2>&1; then
[ -z "$output" ] && fetch -o - "$url" || fetch -o "$output" "$url" _try_fetch
else else
echo "Error: No download utility (curl, wget, or fetch) found." >&2 echo "Error: No download utility (curl, wget, or fetch) found." >&2
return 1 return 1
fi fi
unset -f _try_curl _try_wget _try_fetch
} }
export -f dwl export -f dwl
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -236,13 +258,12 @@ myextip()
shift shift
done done
# Fetch data. Allow overriding endpoint via env var MYEXTIP_URL # Fetch data. Allow overriding endpoint via MYEXTIP_DEFAULT_URL config key.
local MYEXTIP_URL local api_url="${MYEXTIP_DEFAULT_URL:-https://ip-api.com/json/}"
MYEXTIP_URL=${MYEXTIP_URL:-https://ip-api.com/json/}
local response local response
if ! response=$(dwl "$MYEXTIP_URL"); then if ! response=$(dwl "$api_url"); then
disp E "Failed to fetch external IP information from $MYEXTIP_URL" disp E "Failed to fetch external IP information from $api_url"
return 2 return 2
fi fi
@@ -272,3 +293,7 @@ export -f myextip
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# EOF # EOF
load_conf "net"
# EOF

View File

@@ -39,7 +39,7 @@
# Usage: dpkgs <string> # Usage: dpkgs <string>
pkgs() pkgs()
{ {
local ignore_case=0 local ignore_case=${PKGS_DEFAULT_IGNORE_CASE:-0}
local PARSED local PARSED
PARSED=$(getopt -o hi --long help,ignore-case -n 'pkgs' -- "$@") PARSED=$(getopt -o hi --long help,ignore-case -n 'pkgs' -- "$@")
@@ -96,4 +96,6 @@ export -f pkgs
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "packages"
# EOF # EOF

View File

@@ -95,7 +95,7 @@ ppu()
# -u lists processes for a specific user # -u lists processes for a specific user
# -o provides a clean, standard output format # -o provides a clean, standard output format
ps -u "$1" -o pid,user,%cpu,%mem,start,time,command ps -u "$1" -o "${PPU_DEFAULT_FORMAT:-pid,user,%cpu,%mem,start,time,command}"
} }
export -f ppu export -f ppu
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -206,7 +206,7 @@ ku()
disp E "User '$u' does not exist." disp E "User '$u' does not exist."
return 1 return 1
else else
killall -u "$u" killall ${KU_DEFAULT_SIGNAL:+-${KU_DEFAULT_SIGNAL}} -u "$u"
fi fi
done done
} }
@@ -249,5 +249,7 @@ export -f kt
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "processes"
# EOF # EOF

View File

@@ -34,6 +34,134 @@
# * OF SUCH DAMAGE. # * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Parse a prompt theme file safely — it is NEVER sourced or executed.
# Two categories of keys are accepted:
# PROMPT_COLOR_* — prompt slot colours (TIME_FG, BAR_BG, …)
# Standard colour variables from disp.sh (Blue, On_IBlack, …) — allows a
# theme to redefine the palette used everywhere in the shell session.
# Allowed value forms:
# $ColorName or ${ColorName} — colour variable from disp.sh (resolved by
# indirection via ${!varname})
# \e[...m or \033[...m — raw ANSI escape literal (single block)
# Any other key or value is rejected with a warning.
# Usage: load_theme <theme_name_or_path> [theme_dir]
# theme_name_or_path : bare name (e.g. "dark") or an explicit path.
# theme_dir : directory to search for bare names; defaults to
# $MYPATH/profile.d/themes. Overridable via
# PROMPT_THEME_DIR.
load_theme()
{
local theme_name="$1"
local theme_dir="${2:-${PROMPT_THEME_DIR:-$MYPATH/profile.d/themes}}"
local theme_file=""
[[ -z "$theme_name" ]] && return 0
if [[ "$theme_name" == /* || "$theme_name" == */* ]]; then
theme_file="$theme_name"
else
theme_file="$theme_dir/${theme_name}.theme"
fi
if [[ ! -f "$theme_file" || ! -r "$theme_file" ]]; then
printf "[ Warning ] load_theme: theme file not found: %s\n" "$theme_file" >&2
return 1
fi
# ---- Key whitelist: prompt slots ----------------------------------------
local -A _lth_allowed=(
[PROMPT_COLOR_TIME_FG]=1 [PROMPT_COLOR_TIME_BG]=1
[PROMPT_COLOR_BAR_BG]=1
[PROMPT_COLOR_OK_FG]=1 [PROMPT_COLOR_OK_MARK]=1
[PROMPT_COLOR_ERR_BG]=1 [PROMPT_COLOR_ERR_FG]=1 [PROMPT_COLOR_ERR_MARK]=1
[PROMPT_COLOR_ROOT_FG]=1 [PROMPT_COLOR_USER_FG]=1
[PROMPT_COLOR_DIR_FG]=1
)
# ---- Colour variable names exported by disp.sh --------------------------
local _lth_color_re
_lth_color_re='Black|Red|Green|Yellow|Blue|Purple|Cyan|White'
_lth_color_re+='|BBlack|BRed|BGreen|BYellow|BBlue|BPurple|BCyan|BWhite'
_lth_color_re+='|UBlack|URed|UGreen|UYellow|UBlue|UPurple|UCyan|UWhite'
_lth_color_re+='|On_Black|On_Red|On_Green|On_Yellow|On_Blue|On_Purple|On_Cyan|On_White'
_lth_color_re+='|IBlack|IRed|IGreen|IYellow|IBlue|IPurple|ICyan|IWhite'
_lth_color_re+='|BIBlack|BIRed|BIGreen|BIYellow|BIBlue|BIPurple|BICyan|BIWhite'
_lth_color_re+='|On_IBlack|On_IRed|On_IGreen|On_IYellow|On_IBlue|On_IPurple|On_ICyan|On_IWhite'
_lth_color_re+='|DEFAULTFG|DEFAULTBG|DEFAULTCOL|RESETCOL'
# ---- Key whitelist: standard colour vars (same list as above) -----------
local _lth_cn
for _lth_cn in \
Black Red Green Yellow Blue Purple Cyan White \
BBlack BRed BGreen BYellow BBlue BPurple BCyan BWhite \
UBlack URed UGreen UYellow UBlue UPurple UCyan UWhite \
On_Black On_Red On_Green On_Yellow On_Blue On_Purple On_Cyan On_White \
IBlack IRed IGreen IYellow IBlue IPurple ICyan IWhite \
BIBlack BIRed BIGreen BIYellow BIBlue BIPurple BICyan BIWhite \
On_IBlack On_IRed On_IGreen On_IYellow On_IBlue On_IPurple On_ICyan On_IWhite \
DEFAULTFG DEFAULTBG DEFAULTCOL RESETCOL; do
_lth_allowed[$_lth_cn]=1
done
unset _lth_cn
# ERE: safe colour reference $Name or ${Name}
local _lth_ref_re='^\$\{?('"$_lth_color_re"')\}?$'
# ERE: raw ANSI escape literal \e[...m or \033[...m
local _lth_ansi_re='^(\\e|\\033)\[[0-9;]*m$'
# ---- Line parser ---------------------------------------------------------
local _lth_line _lth_key _lth_value _lth_varname _lth_lineno=0
while IFS= read -r _lth_line || [[ -n "$_lth_line" ]]; do
((_lth_lineno++))
_lth_line="${_lth_line%$'\r'}" # strip CR
_lth_line="${_lth_line#"${_lth_line%%[![:space:]]*}"}" # ltrim
_lth_line="${_lth_line%"${_lth_line##*[![:space:]]}"}" # rtrim
[[ -z "$_lth_line" || "$_lth_line" == '#'* ]] && continue # blank/comment
[[ "$_lth_line" == 'export '* ]] && _lth_line="${_lth_line#export }" # strip prefix
if [[ "$_lth_line" != *=* ]]; then
printf "[ Warning ] load_theme: %s:%d: not a key=value pair, ignoring.\n" \
"$theme_file" "$_lth_lineno" >&2
continue
fi
_lth_key="${_lth_line%%=*}"
_lth_value="${_lth_line#*=}"
_lth_key="${_lth_key#"${_lth_key%%[![:space:]]*}"}"
_lth_key="${_lth_key%"${_lth_key##*[![:space:]]}"}" # trim key
if [[ -z "${_lth_allowed[$_lth_key]+x}" ]]; then
printf "[ Warning ] load_theme: %s:%d: key '%s' is not allowed, ignoring.\n" \
"$theme_file" "$_lth_lineno" "$_lth_key" >&2
continue
fi
# Strip surrounding quotes
_lth_value="${_lth_value#\"}" ; _lth_value="${_lth_value%\"}"
_lth_value="${_lth_value#\'}" ; _lth_value="${_lth_value%\'}"
if [[ "$_lth_value" =~ $_lth_ref_re ]]; then
# Safe colour variable reference — resolve via indirection
_lth_varname="${_lth_value#\$}"
_lth_varname="${_lth_varname#\{}"
_lth_varname="${_lth_varname%\}}"
export "$_lth_key"="${!_lth_varname}"
elif [[ "$_lth_value" =~ $_lth_ansi_re ]]; then
# Raw ANSI escape literal — accept as-is
export "$_lth_key"="$_lth_value"
else
printf "[ Warning ] load_theme: %s:%d: invalid value for '%s', ignoring.\n" \
"$theme_file" "$_lth_lineno" "$_lth_key" >&2
fi
done < "$theme_file"
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# timer_* functions : internal timing function for prompt # timer_* functions : internal timing function for prompt
# Usage: timer_now # Usage: timer_now
@@ -95,38 +223,68 @@ set_prompt()
local FancyX='\342\234\227' local FancyX='\342\234\227'
local Checkmark='\342\234\223' local Checkmark='\342\234\223'
# Resolve theme/config colours with hardcoded fallbacks
local _time_fg="${PROMPT_COLOR_TIME_FG:-$Blue}"
local _time_bg="${PROMPT_COLOR_TIME_BG:-$On_IBlack}"
local _bar_bg="${PROMPT_COLOR_BAR_BG:-$On_Blue}"
local _ok_fg="${PROMPT_COLOR_OK_FG:-$White}"
local _ok_mark="${PROMPT_COLOR_OK_MARK:-$Green}"
local _err_bg="${PROMPT_COLOR_ERR_BG:-$On_Red}"
local _err_fg="${PROMPT_COLOR_ERR_FG:-$White}"
local _err_mark="${PROMPT_COLOR_ERR_MARK:-$BYellow}"
local _root_fg="${PROMPT_COLOR_ROOT_FG:-$Red}"
local _user_fg="${PROMPT_COLOR_USER_FG:-$Green}"
local _dir_fg="${PROMPT_COLOR_DIR_FG:-$ICyan}"
# Begin with time # Begin with time
PS1="\[\e[s$Blue$OnGrey [ \t ] $On_Blue" PS1="\[\e[s${_time_fg}${_time_bg} [ \t ] ${_bar_bg}"
# Add a bright white exit status for the last command # Add exit status of the last command.
# If it was successful, print a green check mark. Otherwise, print a red X.
# If it was successful, print a green check mark. Otherwise, print
# a red X.
if [[ $Last_Command == 0 ]]; then if [[ $Last_Command == 0 ]]; then
PS1+="$White$On_Blue [ \$Last_Command " PS1+="${_ok_fg}${_bar_bg} [ \$Last_Command "
PS1+="$Green$Checkmark " PS1+="${_ok_mark}${Checkmark} "
else else
PS1+="$White$On_Red [ \$Last_Command " PS1+="${_err_fg}${_err_bg} [ \$Last_Command "
PS1+="$BYellow$FancyX " PS1+="${_err_mark}${FancyX} "
fi fi
# Add the ellapsed time and current date # Add the elapsed time
timer_stop timer_stop
PS1+="($timer_show)$White ] $On_Blue " PS1+="($timer_show)${_ok_fg} ] ${_bar_bg} "
# If root, just print the host in red. Otherwise, print the current user # If root, print the host in root colour. Otherwise use user colour.
# and host in green.
if [[ $EUID -eq 0 ]]; then if [[ $EUID -eq 0 ]]; then
PS1+="$Red\\u$Green@\\h" PS1+="${_root_fg}\\u${_user_fg}@\\h"
else else
PS1+="$Green\\u@\\h" PS1+="${_user_fg}\\u@\\h"
fi fi
PS1+="\e[K\e[u$DEFAULTCOL\n" PS1+="\e[K\e[u$DEFAULTCOL\n"
# Print the working directory and prompt marker in blue, and reset # Print the working directory and prompt marker, then reset colour.
# the text color to the default. PS1+="${_dir_fg}\\w \\\$$DEFAULTCOL "
PS1+="$ICyan\\w \\\$$DEFAULTCOL "
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Theme and configuration loading.
# Precedence (lowest → highest):
# 1. Hardcoded fallbacks in set_prompt
# 2. Theme file (PROMPT_THEME key from [prompt] section)
# 3. Individual PROMPT_COLOR_* overrides in [prompt] section
#
# CONF_prompt is already populated by parse_conf (run in profile.sh before
# modules are sourced). We extract PROMPT_THEME and PROMPT_THEME_DIR from the
# raw associative array now so load_theme can run before load_conf "prompt"
# exports remaining keys. That way any PROMPT_COLOR_* value set explicitly in
# [prompt] wins over the same variable set by the theme file.
_pt_theme="${CONF_prompt[PROMPT_THEME]:-}"
_pt_dir="${CONF_prompt[PROMPT_THEME_DIR]:-}"
[[ -n "$_pt_theme" ]] && load_theme "$_pt_theme" ${_pt_dir:+"$_pt_dir"}
unset _pt_theme _pt_dir
load_conf "prompt"
# ------------------------------------------------------------------------------
# EOF # EOF

View File

@@ -52,10 +52,13 @@
# The function is very slow on Windows # The function is very slow on Windows
genpwd() genpwd()
{ {
local length=16 local length=${GENPWD_DEFAULT_LENGTH:-16}
local occurs=2 local occurs=${GENPWD_DEFAULT_OCCURS:-2}
local symb=1 maj=1 min=1 numb=1 local symb=${GENPWD_DEFAULT_SYMBOLS:-1}
local nbpwd=1 local maj=${GENPWD_DEFAULT_UPPERCASE:-1}
local min=${GENPWD_DEFAULT_LOWERCASE:-1}
local numb=${GENPWD_DEFAULT_NUMBERS:-1}
local nbpwd=${GENPWD_DEFAULT_COUNT:-1}
local extcar="" local extcar=""
local PARSED local PARSED
@@ -272,7 +275,7 @@ export -f genpwd
# Usage: pwdscore [options] <password> # Usage: pwdscore [options] <password>
pwdscore() pwdscore()
{ {
local verbose=0 local verbose=${PWDSCORE_DEFAULT_VERBOSE:-0}
local read_stdin=0 local read_stdin=0
local password="" local password=""
@@ -474,4 +477,6 @@ export -f pwdscore
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "pwd"
# EOF # EOF

View File

@@ -292,8 +292,10 @@ rain()
printf "Example: rain --color green --speed 3\n" printf "Example: rain --color green --speed 3\n"
} }
local step_duration=0.050 local _raw_speed="${RAIN_DEFAULT_SPEED:-5}"
local base_color="white" local step_duration
step_duration=$(_rain_normalize_speed "$_raw_speed") || step_duration=0.050
local base_color="${RAIN_DEFAULT_COLOR:-white}"
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
case $1 in case $1 in
@@ -360,9 +362,11 @@ matrix()
printf "Example: matrix -C kana -c green --speed 2\n" printf "Example: matrix -C kana -c green --speed 2\n"
} }
local step_duration=0.035 local _raw_speed="${MATRIX_DEFAULT_SPEED:-3.5}"
local base_color="green" local step_duration
local charset="binary" step_duration=$(_rain_normalize_speed "$_raw_speed") || step_duration=0.035
local base_color="${MATRIX_DEFAULT_COLOR:-green}"
local charset="${MATRIX_DEFAULT_CHARSET:-binary}"
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
case $1 in case $1 in
@@ -430,4 +434,7 @@ matrix()
export -f matrix export -f matrix
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "rain"
# EOF # EOF

View File

@@ -186,10 +186,20 @@ ssr()
local srv=$1 local srv=$1
shift shift
ssh -Y root@"$srv" "$@" # Build default options array from config, falling back to -Y (X11 forwarding)
local -a ssh_default_opts=()
if [[ -n "${SSH_DEFAULT_OPT:-}" ]]; then
read -ra ssh_default_opts <<< "${SSH_DEFAULT_OPT}"
else
ssh_default_opts=(-Y)
fi
ssh "${ssh_default_opts[@]}" root@"$srv" "$@"
} }
export -f ssr export -f ssr
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
load_conf "ssh"
# EOF # EOF

42
profile.d/themes/abyss.theme Executable file
View File

@@ -0,0 +1,42 @@
# Abyss prompt theme — deep ocean navy, electric teal, golden accents
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Inspired by the VS Code "Abyss" theme: deep navy/black backdrop, electric
# teal highlights, golden-yellow accents, cool electric blue for identifiers.
# Palette overrides shift the cooler hues to their high-intensity (electric)
# equivalents — blue becomes IBlue, green shifts toward teal (ICyan).
# ------------------------------------------------------------------------------
# Palette overrides — shift colours toward cool electric hues
Blue="\e[0;94m" # electric blue (IBlue — abyss identifier colour)
Green="\e[0;96m" # teal (ICyan — abyss string colour)
Yellow="\e[0;93m" # bright gold (IYellow — abyss constant colour)
PROMPT_COLOR_TIME_FG="$ICyan" # electric teal clock
PROMPT_COLOR_TIME_BG="$On_Black" # deep black background
PROMPT_COLOR_BAR_BG="$On_Blue" # deep blue bar
PROMPT_COLOR_OK_FG="$ICyan" # teal on success
PROMPT_COLOR_OK_MARK="$IGreen" # bright teal-green checkmark
PROMPT_COLOR_ERR_BG="$On_Red" # red background on failure
PROMPT_COLOR_ERR_FG="$IWhite" # bright white text
PROMPT_COLOR_ERR_MARK="$IYellow" # golden X
PROMPT_COLOR_ROOT_FG="$IRed" # red for root
PROMPT_COLOR_USER_FG="$IBlue" # electric blue for user
PROMPT_COLOR_DIR_FG="$ICyan" # teal path

42
profile.d/themes/adwaita.theme Executable file
View File

@@ -0,0 +1,42 @@
# Adwaita prompt theme — clean GNOME defaults, blue accent, green/red status
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Follows the GNOME HIG colour intent: a single calm blue accent (#3584e4),
# pleasant green for success (#33d17a), clear red for errors (#e01b24).
# No intense saturation, no heavy remapping — legibility over spectacle.
# Palette overrides gently shift Blue and Green to their IBlue/IGreen
# variants to better match Adwaita's brighter, flatter tones.
# ------------------------------------------------------------------------------
# Palette overrides — align to Adwaita's brighter accent tones
Blue="\e[0;94m" # IBlue → closer to Adwaita blue (#3584e4)
Green="\e[0;92m" # IGreen → closer to Adwaita green (#33d17a)
PROMPT_COLOR_TIME_FG="$Cyan" # calm cyan clock text
PROMPT_COLOR_TIME_BG="$On_IBlack" # dark grey clock background
PROMPT_COLOR_BAR_BG="$On_Blue" # blue main bar (Adwaita accent)
PROMPT_COLOR_OK_FG="$White" # clean white on success
PROMPT_COLOR_OK_MARK="$Green" # Adwaita green checkmark
PROMPT_COLOR_ERR_BG="$On_Red" # Adwaita red on failure
PROMPT_COLOR_ERR_FG="$White" # white text
PROMPT_COLOR_ERR_MARK="$Yellow" # yellow X (warning intent)
PROMPT_COLOR_ROOT_FG="$Red" # Adwaita red for root
PROMPT_COLOR_USER_FG="$IBlue" # Adwaita blue for user
PROMPT_COLOR_DIR_FG="$IGreen" # Adwaita green for path

32
profile.d/themes/dark.theme Executable file
View File

@@ -0,0 +1,32 @@
# Dark prompt theme — dark grey bar, cyan user, magenta path
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
PROMPT_COLOR_TIME_FG="$ICyan" # Clock text
PROMPT_COLOR_TIME_BG="$On_Black" # Clock background (black)
PROMPT_COLOR_BAR_BG="$On_IBlack" # Main bar background (dark grey)
PROMPT_COLOR_OK_FG="$IGreen" # Exit-code text on success
PROMPT_COLOR_OK_MARK="$BGreen" # Checkmark colour on success
PROMPT_COLOR_ERR_BG="$On_Red" # Exit-code background on failure
PROMPT_COLOR_ERR_FG="$BIWhite" # Exit-code text on failure
PROMPT_COLOR_ERR_MARK="$BIYellow" # X mark colour on failure
PROMPT_COLOR_ROOT_FG="$BIRed" # Username colour when root
PROMPT_COLOR_USER_FG="$ICyan" # Username@host colour for normal users
PROMPT_COLOR_DIR_FG="$IPurple" # Working directory colour

32
profile.d/themes/default.theme Executable file
View File

@@ -0,0 +1,32 @@
# Default prompt theme — blue bar, green user, cyan path
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
PROMPT_COLOR_TIME_FG="$Blue" # Clock text
PROMPT_COLOR_TIME_BG="$On_IBlack" # Clock background (dark grey)
PROMPT_COLOR_BAR_BG="$On_Blue" # Main bar background
PROMPT_COLOR_OK_FG="$White" # Exit-code text on success
PROMPT_COLOR_OK_MARK="$Green" # Checkmark colour on success
PROMPT_COLOR_ERR_BG="$On_Red" # Exit-code background on failure
PROMPT_COLOR_ERR_FG="$White" # Exit-code text on failure
PROMPT_COLOR_ERR_MARK="$BYellow" # X mark colour on failure
PROMPT_COLOR_ROOT_FG="$Red" # Username colour when root
PROMPT_COLOR_USER_FG="$Green" # Username@host colour for normal users
PROMPT_COLOR_DIR_FG="$ICyan" # Working directory colour

35
profile.d/themes/light.theme Executable file
View File

@@ -0,0 +1,35 @@
# Light prompt theme — white bar, blue user, purple path
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Opposite of dark.theme: backgrounds flip to bright whites, foregrounds
# shift to their dark/regular equivalents for contrast on a light terminal.
# ------------------------------------------------------------------------------
PROMPT_COLOR_TIME_FG="$Blue" # Clock text (ICyan → Blue, darker for light bg)
PROMPT_COLOR_TIME_BG="$On_IWhite" # Clock background (On_Black → On_IWhite)
PROMPT_COLOR_BAR_BG="$On_White" # Main bar background (On_IBlack → On_White)
PROMPT_COLOR_OK_FG="$Green" # Exit-code text on success (IGreen → Green)
PROMPT_COLOR_OK_MARK="$BGreen" # Checkmark colour on success (unchanged — bold green reads on both)
PROMPT_COLOR_ERR_BG="$On_Red" # Exit-code background on failure (unchanged)
PROMPT_COLOR_ERR_FG="$BIWhite" # Exit-code text on failure (unchanged — white on red works on both)
PROMPT_COLOR_ERR_MARK="$BYellow" # X mark on failure (BIYellow → BYellow, less glaring on light)
PROMPT_COLOR_ROOT_FG="$Red" # Username when root (BIRed → Red)
PROMPT_COLOR_USER_FG="$Blue" # Username@host normal user (ICyan → Blue)
PROMPT_COLOR_DIR_FG="$Purple" # Working directory (IPurple → Purple)

View File

@@ -0,0 +1,64 @@
# Monochrome prompt theme — strict greyscale, no hue at all
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# All hues are silenced — colour variables are remapped to greyscale ANSI
# codes so that ls, man, grep, etc. also lose their colour cues. Contrast
# is achieved entirely through brightness: dark grey / light grey / white.
# Error state uses an inverted (white background, black text) bar so it
# remains visually distinct without relying on red.
# ------------------------------------------------------------------------------
# Palette overrides — replace every hue with a grey equivalent
Red="\e[0;37m" # light grey
Green="\e[0;97m" # bright white (success intent kept as brightest)
Yellow="\e[0;90m" # dark grey
Blue="\e[0;90m" # dark grey
Purple="\e[0;37m" # light grey
Cyan="\e[0;37m" # light grey
BRed="\e[1;37m" # bold light grey
BGreen="\e[1;97m" # bold bright white
BYellow="\e[1;90m" # bold dark grey
BBlue="\e[1;90m" # bold dark grey
BPurple="\e[1;37m" # bold light grey
BCyan="\e[1;37m" # bold light grey
IRed="\e[0;97m" # bright white
IGreen="\e[0;97m" # bright white
IYellow="\e[0;90m" # dark grey
IBlue="\e[0;90m" # dark grey
IPurple="\e[0;37m" # light grey
ICyan="\e[0;37m" # light grey
BIRed="\e[1;97m" # bold bright white
BIGreen="\e[1;97m" # bold bright white
BIYellow="\e[1;90m" # bold dark grey
BIBlue="\e[1;90m" # bold dark grey
BIPurple="\e[1;37m" # bold light grey
BICyan="\e[1;37m" # bold light grey
PROMPT_COLOR_TIME_FG="$IBlack" # dark grey clock text (subtle)
PROMPT_COLOR_TIME_BG="$On_IBlack" # dark grey clock background
PROMPT_COLOR_BAR_BG="$On_IBlack" # dark grey main bar
PROMPT_COLOR_OK_FG="$IWhite" # bright white on success
PROMPT_COLOR_OK_MARK="$BIWhite" # bold bright white checkmark
PROMPT_COLOR_ERR_BG="$On_White" # inverted: bright white bar on error
PROMPT_COLOR_ERR_FG="$Black" # black text on white background
PROMPT_COLOR_ERR_MARK="$BBlack" # bold black X
PROMPT_COLOR_ROOT_FG="$BIWhite" # bold bright white for root warning
PROMPT_COLOR_USER_FG="$IWhite" # bright white for normal user
PROMPT_COLOR_DIR_FG="$White" # standard white for path

45
profile.d/themes/monokai.theme Executable file
View File

@@ -0,0 +1,45 @@
# Monokai prompt theme — high-saturation, vivid hues on near-black
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Monokai's signature: lime green, orange-yellow, hot pink/red, bright violet,
# electric cyan — all on a near-black (#272822) background.
# Palette overrides remap the dim ANSI regulars to their vivid high-intensity
# equivalents so that ls, grep colour output, etc. also look more "Monokai".
# ------------------------------------------------------------------------------
# Palette overrides — boost regular colours to Monokai-vivid equivalents
Red="\e[0;91m" # hot pink/red (#F92672)
Green="\e[0;92m" # lime green (#A6E22E)
Yellow="\e[0;93m" # orange-yellow (#E6DB74 / #FD971F)
Blue="\e[0;94m" # electric blue (#66D9E8 → shift blue)
Purple="\e[0;95m" # bright violet (#AE81FF)
Cyan="\e[0;96m" # electric cyan (#66D9E8)
PROMPT_COLOR_TIME_FG="$IYellow" # orange clock text
PROMPT_COLOR_TIME_BG="$On_IBlack" # near-black Monokai background
PROMPT_COLOR_BAR_BG="$On_IBlack" # flat dark bar
PROMPT_COLOR_OK_FG="$IGreen" # lime green on success
PROMPT_COLOR_OK_MARK="$IGreen" # lime green checkmark
PROMPT_COLOR_ERR_BG="$On_IBlack" # keep dark — use colour for contrast
PROMPT_COLOR_ERR_FG="$IRed" # hot pink on failure
PROMPT_COLOR_ERR_MARK="$IRed" # hot pink X
PROMPT_COLOR_ROOT_FG="$IRed" # hot pink for root
PROMPT_COLOR_USER_FG="$IYellow" # orange-yellow for user
PROMPT_COLOR_DIR_FG="$ICyan" # electric cyan for path

42
profile.d/themes/plasma.theme Executable file
View File

@@ -0,0 +1,42 @@
# Plasma prompt theme — vivid KDE Plasma purples and electric cyan
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Captures the charged, vivid energy of KDE Plasma: dominant bright magenta/
# purple, electric cyan highlights, all on a dark background. Palette overrides
# boost Blue, Purple, and Cyan to their high-intensity equivalents so that
# shell colour output reflects the same vivid palette.
# ------------------------------------------------------------------------------
# Palette overrides — vivid charged hues
Blue="\e[0;94m" # electric blue (IBlue)
Purple="\e[0;95m" # vivid magenta (IPurple — Plasma's signature colour)
Cyan="\e[0;96m" # electric cyan (ICyan)
PROMPT_COLOR_TIME_FG="$IPurple" # vivid purple clock text
PROMPT_COLOR_TIME_BG="$On_IBlack" # dark grey background
PROMPT_COLOR_BAR_BG="$On_Purple" # bright magenta bar
PROMPT_COLOR_OK_FG="$ICyan" # electric cyan on success
PROMPT_COLOR_OK_MARK="$IGreen" # green checkmark
PROMPT_COLOR_ERR_BG="$On_Red" # red bar on failure
PROMPT_COLOR_ERR_FG="$IWhite" # bright white text
PROMPT_COLOR_ERR_MARK="$IYellow" # yellow X
PROMPT_COLOR_ROOT_FG="$IRed" # red for root
PROMPT_COLOR_USER_FG="$BIPurple" # bold vivid purple for user
PROMPT_COLOR_DIR_FG="$ICyan" # electric cyan path

View File

@@ -0,0 +1,127 @@
# Solarized Light prompt theme — exact 24-bit / true-colour palette
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Requires a terminal with true-colour / 24-bit support.
# Check with: printf '\e[38;2;220;50;47mred\e[0m\n'
# If you see solid red text, your terminal supports this theme.
# (konsole, iTerm2, kitty, alacritty, Windows Terminal all do)
#
# Solarized Light base tones (inverted vs Dark):
# Base3 #fdf6e3 →253 246 227 (main background — lightest)
# Base2 #eee8d5 →238 232 213 (background highlights)
# Base1 #93a1a1 →147 161 161 (comments / secondary content)
# Base0 #839496 →131 148 150 (body text — secondary)
# Base00 #657b83 →101 123 131 (body text — main on light bg)
# Base01 #586e75 → 88 110 117 (emphasis)
# Base02 #073642 → 7 54 66 (darkest — used for strong contrast)
#
# Accent colours are identical to Solarized Dark:
# Yellow #b58900 →181 137 0
# Orange #cb4b16 →203 75 22
# Red #dc322f →220 50 47
# Magenta #d33682 →211 54 130
# Violet #6c71c4 →108 113 196
# Blue #268bd2 → 38 139 210
# Cyan #2aa198 → 42 161 152
# Green #859900 →133 153 0
# ------------------------------------------------------------------------------
# ---- Foreground palette overrides -------------------------------------------
# The accent fg colours are identical to Dark — only the base/neutral roles flip.
# Regular
Black="\e[38;2;253;246;227m" # Base3 — lightest (fg on light bg = invisible; used as bg fg pair complement)
Red="\e[38;2;220;50;47m" # Red
Green="\e[38;2;133;153;0m" # Green
Yellow="\e[38;2;181;137;0m" # Yellow — primary accent
Blue="\e[38;2;38;139;210m" # Blue
Purple="\e[38;2;211;54;130m" # Magenta
Cyan="\e[38;2;42;161;152m" # Cyan
White="\e[38;2;101;123;131m" # Base00 — main body text on light bg
# Bold
BBlack="\e[1;38;2;238;232;213m" # Base2 bold
BRed="\e[1;38;2;220;50;47m" # Red bold
BGreen="\e[1;38;2;133;153;0m" # Green bold
BYellow="\e[1;38;2;181;137;0m" # Yellow bold
BBlue="\e[1;38;2;38;139;210m" # Blue bold
BPurple="\e[1;38;2;211;54;130m" # Magenta bold
BCyan="\e[1;38;2;42;161;152m" # Cyan bold
BWhite="\e[1;38;2;88;110;117m" # Base01 bold — emphasis text
# High intensity (emphasis / I* family)
IBlack="\e[38;2;147;161;161m" # Base1 — secondary/comments
IRed="\e[38;2;203;75;22m" # Orange — Solarized's "bright red"
IGreen="\e[38;2;133;153;0m" # Green (no brighter variant)
IYellow="\e[38;2;181;137;0m" # Yellow (no brighter variant)
IBlue="\e[38;2;108;113;196m" # Violet — Solarized's "bright blue"
IPurple="\e[38;2;211;54;130m" # Magenta (no brighter variant)
ICyan="\e[38;2;42;161;152m" # Cyan (no brighter variant)
IWhite="\e[38;2;88;110;117m" # Base01 — emphasis
# Bold high intensity
BIBlack="\e[1;38;2;147;161;161m" # Base1 bold
BIRed="\e[1;38;2;203;75;22m" # Orange bold
BIGreen="\e[1;38;2;133;153;0m" # Green bold
BIYellow="\e[1;38;2;181;137;0m" # Yellow bold
BIBlue="\e[1;38;2;108;113;196m" # Violet bold
BIPurple="\e[1;38;2;211;54;130m" # Magenta bold
BICyan="\e[1;38;2;42;161;152m" # Cyan bold
BIWhite="\e[1;38;2;88;110;117m" # Base01 bold
# ---- Background palette overrides -------------------------------------------
# Light bases flip: On_Black → Base3 (lightest), On_IBlack → Base2 (highlights)
On_Black="\e[48;2;253;246;227m" # Base3 — main light background
On_Red="\e[48;2;220;50;47m" # Red
On_Green="\e[48;2;133;153;0m" # Green
On_Yellow="\e[48;2;181;137;0m" # Yellow
On_Blue="\e[48;2;38;139;210m" # Blue
On_Purple="\e[48;2;211;54;130m" # Magenta
On_Cyan="\e[48;2;42;161;152m" # Cyan
On_White="\e[48;2;101;123;131m" # Base00
On_IBlack="\e[48;2;238;232;213m" # Base2 — background highlights (slightly darker than Base3)
On_IRed="\e[48;2;203;75;22m" # Orange
On_IGreen="\e[48;2;133;153;0m" # Green
On_IYellow="\e[48;2;181;137;0m" # Yellow
On_IBlue="\e[48;2;108;113;196m" # Violet
On_IPurple="\e[48;2;211;54;130m" # Magenta
On_ICyan="\e[48;2;42;161;152m" # Cyan
On_IWhite="\e[48;2;88;110;117m" # Base01
# ---- Special codes ----------------------------------------------------------
DEFAULTFG="\e[38;2;101;123;131m" # Base00 — default foreground on light bg
DEFAULTBG="\e[48;2;253;246;227m" # Base3 — default background
RESETCOL="\e[0m"
# ---- Prompt colour slots ----------------------------------------------------
# All specified as direct ANSI sequences to avoid ordering dependencies
# with the palette overrides above.
PROMPT_COLOR_TIME_FG="\e[38;2;181;137;0m" # Yellow — primary accent
PROMPT_COLOR_TIME_BG="\e[48;2;238;232;213m" # Base2 — slightly darker than bg
PROMPT_COLOR_BAR_BG="\e[48;2;238;232;213m" # Base2 — warm light bar
PROMPT_COLOR_OK_FG="\e[38;2;7;54;66m" # Base02 — dark text for contrast on light
PROMPT_COLOR_OK_MARK="\e[38;2;133;153;0m" # Green — checkmark
PROMPT_COLOR_ERR_BG="\e[48;2;220;50;47m" # Red — error background
PROMPT_COLOR_ERR_FG="\e[38;2;253;246;227m" # Base3 — light text on red
PROMPT_COLOR_ERR_MARK="\e[38;2;253;246;227m" # Base3 — X mark (bright on red)
PROMPT_COLOR_ROOT_FG="\e[38;2;220;50;47m" # Red — root warning
PROMPT_COLOR_USER_FG="\e[38;2;42;161;152m" # Cyan — normal user
PROMPT_COLOR_DIR_FG="\e[38;2;38;139;210m" # Blue — working directory

122
profile.d/themes/solarized.theme Executable file
View File

@@ -0,0 +1,122 @@
# Solarized Dark prompt theme — exact 24-bit / true-colour palette
# ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted:
#
# KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block)
#
# Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session)
#
# Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code.
# ------------------------------------------------------------------------------
# Requires a terminal with true-colour / 24-bit support.
# Check with: printf '\e[38;2;220;50;47mred\e[0m\n'
# If you see solid red text, your terminal supports this theme.
# (konsole, iTerm2, kitty, alacritty, Windows Terminal all do)
#
# Solarized Dark exact hex → RGB mapping used below:
# Base03 #002b36 → 0 43 54 (darkest background)
# Base02 #073642 → 7 54 66 (background highlights)
# Base01 #586e75 → 88 110 117 (comments / secondary content)
# Base00 #657b83 →101 123 131 (body text — dark background)
# Base0 #839496 →131 148 150 (body text — main)
# Base1 #93a1a1 →147 161 161 (optional emphasis)
# Yellow #b58900 →181 137 0
# Orange #cb4b16 →203 75 22
# Red #dc322f →220 50 47
# Magenta #d33682 →211 54 130
# Violet #6c71c4 →108 113 196
# Blue #268bd2 → 38 139 210
# Cyan #2aa198 → 42 161 152
# Green #859900 →133 153 0
# ------------------------------------------------------------------------------
# ---- Foreground palette overrides -------------------------------------------
# Regular
Black="\e[38;2;0;43;54m" # Base03 — darkest content fg
Red="\e[38;2;220;50;47m" # Red
Green="\e[38;2;133;153;0m" # Green
Yellow="\e[38;2;181;137;0m" # Yellow — primary accent
Blue="\e[38;2;38;139;210m" # Blue
Purple="\e[38;2;211;54;130m" # Magenta
Cyan="\e[38;2;42;161;152m" # Cyan
White="\e[38;2;131;148;150m" # Base0 — body text
# Bold
BBlack="\e[1;38;2;7;54;66m" # Base02 bold
BRed="\e[1;38;2;220;50;47m" # Red bold
BGreen="\e[1;38;2;133;153;0m" # Green bold
BYellow="\e[1;38;2;181;137;0m" # Yellow bold
BBlue="\e[1;38;2;38;139;210m" # Blue bold
BPurple="\e[1;38;2;211;54;130m" # Magenta bold
BCyan="\e[1;38;2;42;161;152m" # Cyan bold
BWhite="\e[1;38;2;147;161;161m" # Base1 bold
# High intensity (brighter / emphasis roles in Solarized)
IBlack="\e[38;2;88;110;117m" # Base01 — secondary/comments
IRed="\e[38;2;203;75;22m" # Orange — Solarized's "bright red"
IGreen="\e[38;2;133;153;0m" # Green (no brighter variant)
IYellow="\e[38;2;181;137;0m" # Yellow (no brighter variant)
IBlue="\e[38;2;108;113;196m" # Violet — Solarized's "bright blue"
IPurple="\e[38;2;211;54;130m" # Magenta (no brighter variant)
ICyan="\e[38;2;42;161;152m" # Cyan (no brighter variant)
IWhite="\e[38;2;147;161;161m" # Base1 — optional emphasis
# Bold high intensity
BIBlack="\e[1;38;2;88;110;117m" # Base01 bold
BIRed="\e[1;38;2;203;75;22m" # Orange bold
BIGreen="\e[1;38;2;133;153;0m" # Green bold
BIYellow="\e[1;38;2;181;137;0m" # Yellow bold
BIBlue="\e[1;38;2;108;113;196m" # Violet bold
BIPurple="\e[1;38;2;211;54;130m" # Magenta bold
BICyan="\e[1;38;2;42;161;152m" # Cyan bold
BIWhite="\e[1;38;2;147;161;161m" # Base1 bold
# ---- Background palette overrides -------------------------------------------
On_Black="\e[48;2;0;43;54m" # Base03
On_Red="\e[48;2;220;50;47m" # Red
On_Green="\e[48;2;133;153;0m" # Green
On_Yellow="\e[48;2;181;137;0m" # Yellow
On_Blue="\e[48;2;38;139;210m" # Blue
On_Purple="\e[48;2;211;54;130m" # Magenta
On_Cyan="\e[48;2;42;161;152m" # Cyan
On_White="\e[48;2;131;148;150m" # Base0
On_IBlack="\e[48;2;7;54;66m" # Base02 — background highlights
On_IRed="\e[48;2;203;75;22m" # Orange
On_IGreen="\e[48;2;133;153;0m" # Green
On_IYellow="\e[48;2;181;137;0m" # Yellow
On_IBlue="\e[48;2;108;113;196m" # Violet
On_IPurple="\e[48;2;211;54;130m" # Magenta
On_ICyan="\e[48;2;42;161;152m" # Cyan
On_IWhite="\e[48;2;147;161;161m" # Base1
# ---- Special codes ----------------------------------------------------------
DEFAULTFG="\e[38;2;131;148;150m" # Base0 — default foreground
DEFAULTBG="\e[48;2;0;43;54m" # Base03 — default background
RESETCOL="\e[0m"
# ---- Prompt colour slots ----------------------------------------------------
# All specified as direct ANSI sequences to avoid ordering dependencies
# with the palette overrides above.
PROMPT_COLOR_TIME_FG="\e[38;2;181;137;0m" # Yellow — primary accent
PROMPT_COLOR_TIME_BG="\e[48;2;0;43;54m" # Base03 — darkest background
PROMPT_COLOR_BAR_BG="\e[48;2;7;54;66m" # Base02 — bar background
PROMPT_COLOR_OK_FG="\e[38;2;131;148;150m" # Base0 — body text on success
PROMPT_COLOR_OK_MARK="\e[38;2;133;153;0m" # Green — checkmark
PROMPT_COLOR_ERR_BG="\e[48;2;220;50;47m" # Red — error background
PROMPT_COLOR_ERR_FG="\e[38;2;253;246;227m" # Base3 — bright fg on red
PROMPT_COLOR_ERR_MARK="\e[38;2;181;137;0m" # Yellow — X mark on red bg
PROMPT_COLOR_ROOT_FG="\e[38;2;220;50;47m" # Red — root warning
PROMPT_COLOR_USER_FG="\e[38;2;42;161;152m" # Cyan — normal user
PROMPT_COLOR_DIR_FG="\e[38;2;38;139;210m" # Blue — working directory

View File

@@ -35,8 +35,14 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
export BASE_URL="https://git.geoffray-levasseur.org/fatalerrors/profile" export BASE_URL="https://git.geoffray-levasseur.org/fatalerrors/profile"
export UPDT_URL="$BASE_URL/raw/branch/master"
export ARCH_URL="$BASE_URL/archive/master.tar.gz" # Load [updates] configuration before building the URLs so that
# UPDT_DEFAULT_BRANCH (if set in profile.conf) is already available.
load_conf "updates"
export UPDT_DEFAULT_BRANCH="${UPDT_DEFAULT_BRANCH:-master}"
export UPDT_URL="$BASE_URL/raw/branch/$UPDT_DEFAULT_BRANCH"
export ARCH_URL="$BASE_URL/archive/$UPDT_DEFAULT_BRANCH.tar.gz"
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Check whether a newer profile version is available # Check whether a newer profile version is available
@@ -251,6 +257,35 @@ profile_upgrade()
popd >/dev/null || return 1 popd >/dev/null || return 1
return 3 return 3
} }
# Resolve the target branch: explicit -b flag > config default > master
local target_branch="${branch:-${UPDT_DEFAULT_BRANCH:-master}}"
branch="$target_branch"
# Detect current local branch and warn+switch when it differs
local current_branch
current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
if [[ -n "$current_branch" && "$current_branch" != "$branch" ]]; then
disp W "Branch mismatch: currently on '$current_branch', configured branch is '$branch'."
if (( dry_run )); then
disp I "[dry-run] git fetch origin $branch"
disp I "[dry-run] git checkout $branch"
disp W "[dry-run] Branch would be changed from '$current_branch' to '$branch'."
else
git fetch origin "$branch" || {
disp E "Git fetch failed for branch $branch."
popd >/dev/null || return 1
return 2
}
git checkout "$branch" || {
disp E "Git checkout failed for branch $branch."
popd >/dev/null || return 1
return 2
}
disp W "Branch has been changed from '$current_branch' to '$branch'."
fi
fi
if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then
if (( force_git )); then if (( force_git )); then
disp W "Force mode: local Git changes and untracked files will be lost." disp W "Force mode: local Git changes and untracked files will be lost."
@@ -281,44 +316,14 @@ profile_upgrade()
disp W "Upgrade may fail if the changes conflict with the upgrade." disp W "Upgrade may fail if the changes conflict with the upgrade."
fi fi
fi fi
if [[ -n "$branch" ]]; then
if (( dry_run )); then
disp I "[dry-run] git fetch origin $branch"
disp I "[dry-run] git checkout $branch"
else
git fetch origin "$branch" || {
disp E "Git fetch failed for branch $branch."
popd >/dev/null || return 1
return 2
}
git checkout "$branch" || {
disp E "Git checkout failed for branch $branch."
popd >/dev/null || return 1
return 2
}
fi
fi
if (( dry_run )); then if (( dry_run )); then
if [[ -n "$branch" ]]; then disp I "[dry-run] git pull origin $branch"
disp I "[dry-run] git pull origin $branch"
else
disp I "[dry-run] git pull"
fi
else else
if [[ -n "$branch" ]]; then git pull origin "$branch" || {
git pull origin "$branch" || { disp E "Git pull failed, upgrade not applied."
disp E "Git pull failed, upgrade not applied." popd >/dev/null || return 1
popd >/dev/null || return 1 return 2
return 2 }
}
else
git pull || {
disp E "Git pull failed, upgrade not applied."
popd >/dev/null || return 1
return 2
}
fi
disp I "Successfully upgraded using git." disp I "Successfully upgraded using git."
fi fi
popd >/dev/null || return 1 popd >/dev/null || return 1

View File

@@ -1 +1 @@
3.95.3-4_beta_3 3.99.1-4_rc_1