50 Commits

Author SHA1 Message Date
fatalerrors
ee72ede116 update doc and release 4.1.0 2026-05-07 15:03:23 +02:00
fatalerrors
f5244ac062 allow the profile to self install 2026-05-07 11:54:06 +02:00
fatalerrors
9a089112c3 make help better 2026-05-07 11:53:28 +02:00
fatalerrors
e64a857a43 fix too long long on non functionnal networt (and improve dwl) 2026-05-07 11:52:53 +02:00
fatalerrors
ddd7d4193a version bump 2026-05-06 18:28:25 +02:00
fatalerrors
83a1c8ce48 removed rogue french comments 2026-05-06 18:28:06 +02:00
fatalerrors
b29fa3b30c make get_pkgmgr public 2026-05-06 18:27:19 +02:00
fatalerrors
cd0bcfd214 fix completion 2026-05-06 18:24:38 +02:00
fatalerrors
a91c41871a fix completion 2026-05-06 18:20:30 +02:00
fatalerrors
9698f0e506 fix completion 2026-05-06 18:12:14 +02:00
fatalerrors
9e22f007b9 make disp smarter 2026-05-06 18:05:51 +02:00
fatalerrors
d472fb61aa load completion 2026-05-06 15:35:05 +02:00
fatalerrors
9108ee8266 add primary completion for git 2026-05-06 15:34:19 +02:00
fatalerrors
a7f7452b2b add auto to gacp 2026-05-05 16:25:13 +02:00
fatalerrors
bc67399ebc Merge branch '4.x' 2026-04-23 17:59:07 +02:00
fatalerrors
02b037d0fc proper changelog, removed the old history.txt file 2026-04-23 17:57:01 +02:00
fatalerrors
e567957ea0 update doc 2026-04-23 17:36:25 +02:00
fatalerrors
67bdd3e863 add gacp 2026-04-23 17:31:33 +02:00
fatalerrors
fa573bce8f add git helpers 2026-04-23 17:18:01 +02:00
fatalerrors
241d53ebc4 Merge branch '4.x' 2026-04-22 17:58:21 +02:00
fatalerrors
1225230a07 4.0 released 2026-04-22 17:56:08 +02:00
fatalerrors
9c43190202 bugfix: removed last french words and frenglish 2026-04-22 17:54:42 +02:00
fatalerrors
9477638a28 bugfix: no error on missing configuration, just use default 2026-04-22 17:16:33 +02:00
fatalerrors
f16ad711fb color adjustments 2026-04-21 16:51:57 +02:00
fatalerrors
15ef317029 themes adjustments 2026-04-21 16:07:16 +02:00
fatalerrors
a6e4d7a256 get ready for release 2026-04-21 15:24:04 +02:00
fatalerrors
6106ca7684 proper package manager detection 2026-04-21 14:18:37 +02:00
fatalerrors
1088029ae6 fix extra shift 2026-04-21 14:03:57 +02:00
fatalerrors
eb4c89759b fix display in kt 2026-04-21 14:03:22 +02:00
fatalerrors
1dc5d72ac6 fix display of return code in prompt 2026-04-21 14:02:45 +02:00
fatalerrors
d49703c5d5 fix themes right 2026-04-18 00:19:07 +02:00
fatalerrors
066f2e353e fix all spellsheck 2026-04-16 17:53:46 +02:00
fatalerrors
c011f03aee add missing help 2026-04-15 17:47:15 +02:00
fatalerrors
c4b0516c45 fix hardcoded setfr in main file 2026-04-15 17:36:15 +02:00
fatalerrors
4da29872fc refining themes 2026-04-15 17:00:04 +02:00
fatalerrors
d7a0e2c5f5 refining themes 2026-04-15 16:53:33 +02:00
fatalerrors
d60a93814b typo 2026-04-15 16:34:54 +02:00
fatalerrors
d27935eedd bugfix 2026-04-15 16:33:45 +02:00
fatalerrors
e77232b3ca bugfix 2026-04-15 16:29:04 +02:00
fatalerrors
d6dce2d91e bugfix 2026-04-15 16:08:34 +02:00
fatalerrors
4e3cccff64 bugfix 2026-04-15 16:03:10 +02:00
fatalerrors
91f033743d bugfix 2026-04-15 15:54:58 +02:00
fatalerrors
9fcf21c55e bugfix 2026-04-15 15:45:55 +02:00
fatalerrors
5300386941 bugfix 2026-04-15 15:39:45 +02:00
fatalerrors
dfad345be3 reset color definitions before loading a new theme 2026-04-15 15:16:11 +02:00
fatalerrors
1b16878ea8 allow dynamic theme change 2026-04-15 15:03:43 +02:00
fatalerrors
30b8b8241a bugfix 2026-04-15 14:54:49 +02:00
fatalerrors
a4056b9e82 fix line ending 2026-04-15 14:53:55 +02:00
fatalerrors
6696e0d05a fix help 2026-04-15 14:44:33 +02:00
fatalerrors
6d15af029e fix mod 2026-04-15 14:25:12 +02:00
39 changed files with 3449 additions and 1781 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
# User-specific configuration — never commit personal settings.
# Copy doc/profile.conf.example to profile.conf and customise it.
profile.conf
# Compiled / generated artefacts
*.pyc
__pycache__/
# macOS noise
.DS_Store
# Editor swap / backup files
*~
*.swp
*.swo

View File

@@ -1,4 +1,4 @@
Copyright 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org> Copyright 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
This is distributed with BSD-3-Clause license with the following terms and This is distributed with BSD-3-Clause license with the following terms and
condition: condition:

View File

@@ -10,12 +10,28 @@ current shell is not bash.
## 2. Getting started ## 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 directory.
add at the end (preferably):
The profile is designed to be **sourced**, not executed directly.
Manual setup:
```bash ```bash
source <installpath>/profile/profile.sh source <installpath>/profile/profile.sh
``` ```
Automatic setup (recommended):
```bash
bash <installpath>/profile/profile.sh --install
```
`--install` appends the required `source` line to both `~/.bashrc` and
`~/.profile` by default. You can target one file only:
```bash
bash <installpath>/profile/profile.sh --install --bashrc
bash <installpath>/profile/profile.sh --install --profile
```
You may also set the `PROFILE_PATH` environment variable before sourcing if you You may also set the `PROFILE_PATH` environment variable before sourcing if you
want to override the automatic path detection: want to override the automatic path detection:
```bash ```bash
@@ -49,18 +65,26 @@ A bar-style prompt showing current time, execution time of the last command
| Function | Module | Description | | Function | Module | Description |
|---|---|---| |---|---|---|
| `busy` | fun | Monitor /dev/urandom for a hex pattern — look busy | | `busy` | fun | Monitor /dev/urandom for a hex pattern — look busy |
| `check_updates` | updates | Check whether a newer profile version is available online | | `check_updates` | updates | Check whether a newer profile version is available online; when called with `-q` at startup a 3-second network timeout is applied so a slow or absent network never delays the prompt |
| `clean` | filefct | Erase backup files in given directories, optionally recursive | | `clean` | filefct | Erase backup files in given directories, optionally recursive |
| `disp` | disp | Display formatted info / warning / error / debug messages | | `disp` | disp | Display formatted info / warning / error / debug messages; long messages are word-wrapped and continuation lines are indented to align with the message text |
| `dwl` | net | Download a URL using curl, wget, or fetch transparently | | `dwl` | net | Download a URL using curl, wget, or fetch transparently; supports `-t <seconds>` / `--timeout <seconds>` to cap the transfer time |
| `expandlist` | filefct | Expand glob expressions into a quoted, separated list | | `expandlist` | filefct | Expand glob expressions into a quoted, separated list |
| `file_stats` | filefct | Display file size statistics for a path | | `file_stats` | filefct | Display file size statistics for a path |
| `findbig` | filefct | Find the biggest files in the given or current directory | | `findbig` | filefct | Find the biggest files in the given or current directory |
| `finddead` | filefct | Find dead symbolic links 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 | | `findzero` | filefct | Find empty files in the given or current directory |
| `gacp` | git | Add, commit and push changes; auto-pulls with rebase first if needed |
| `genpwd` | pwd | Generate one or more random secure passwords with configurable constraints | | `genpwd` | pwd | Generate one or more random secure passwords with configurable constraints |
| `ggraph` | git | Display a decorated git history graph |
| `gpid` | processes | Give the list of PIDs matching the given process name(s) | | `gpid` | processes | Give the list of PIDs matching the given process name(s) |
| `help` | help | Display the list of available functions and basic usage | | `gprune` | git | Delete local branches already merged into the main branch |
| `greset` | git | Reset the current branch to upstream, stashing local changes first |
| `groot` | git | Display the repository root path, or change directory to it with `-g` |
| `gsync` | git | Fetch and rebase the current branch onto its upstream |
| `gst` | git | Display compact git status with branch tracking information |
| `gwip` | git | Create a quick WIP checkpoint commit |
| `help` | help | Display the list of available functions and basic usage; `help <command>` delegates to `<command> --help` |
| `isipv4` | net | Tell if the given parameter is a valid IPv4 address | | `isipv4` | net | Tell if the given parameter is a valid IPv4 address |
| `isipv6` | net | Tell if the given parameter is a valid IPv6 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 | | `ku` | processes | Kill all processes owned by the given user name or ID |
@@ -68,7 +92,8 @@ A bar-style prompt showing current time, execution time of the last command
| `mcd` | filefct | Create a directory and immediately move into it | | `mcd` | filefct | Create a directory and immediately move into it |
| `meteo` | info | Display weather forecast for the configured or given city | | `meteo` | info | Display weather forecast for the configured or given city |
| `myextip` | net | Get information about your public IP address | | `myextip` | net | Get information about your public IP address |
| `pkgs` | packages | Search for a pattern in installed package names (dpkg/rpm, supports `-i`) | | `get_pkgmgr` | packages | Detect the active package manager of the running distribution (`apt`, `dnf`, `yum`, `zypper`, `pacman`, `apk`, `portage`, `xbps`, `nix`) |
| `pkgs` | packages | Search for a pattern in installed package names (distro-aware via `get_pkgmgr`, supports `-i`) |
| `ppg` | processes | Look for the given pattern in running processes | | `ppg` | processes | Look for the given pattern in running processes |
| `ppn` | processes | List processes matching an exact command name | | `ppn` | processes | List processes matching an exact command name |
| `ppu` | processes | List processes owned by a specific user | | `ppu` | processes | List processes owned by a specific user |
@@ -90,6 +115,13 @@ A bar-style prompt showing current time, execution time of the last command
Locale shortcut functions (`setfr`, `setus`, etc.) are dynamically generated at Locale shortcut functions (`setfr`, `setus`, etc.) are dynamically generated at
startup from the `SET_LOCALE` configuration key (see section 4). startup from the `SET_LOCALE` configuration key (see section 4).
### 3.3. Bash completion
profile loads all `*.sh` files found under `profile.d/bash-completion/`
automatically in interactive sessions. This directory is the right place to add
any custom completion definitions. profile already ships completions for its git
helper functions there (`git-completion.sh`).
## 4. Configuration ## 4. Configuration
profile uses an INI-style configuration file (`profile.conf`) located in the profile uses an INI-style configuration file (`profile.conf`) located in the
same directory as `profile.sh`. Sections are declared with `[section_name]` and same directory as `profile.sh`. Sections are declared with `[section_name]` and
@@ -170,6 +202,15 @@ change the default without having to pass flags every time.
| `BUSY_DEFAULT_PATTERN` | `[0-9a-f]` | Hex pattern matched by `busy` | | `BUSY_DEFAULT_PATTERN` | `[0-9a-f]` | Hex pattern matched by `busy` |
| `BUSY_DEFAULT_DELAY` | `0.1` | Polling delay (seconds) for `busy` | | `BUSY_DEFAULT_DELAY` | `0.1` | Polling delay (seconds) for `busy` |
**`[git]`**
| Key | Default | Description |
|---|---|---|
| `GIT_MAIN_BRANCH` | `main` | Fallback main branch name used when remote HEAD cannot be detected |
| `GIT_DEFAULT_REMOTE` | `origin` | Default remote used by git helper functions |
| `GIT_WIP_PREFIX` | `wip` | Prefix used by `gwip` when generating automatic checkpoint messages |
| `GIT_GACP_AUTO_ADD` | `1` | Set to `1` to make `gacp` automatically add all modified files when no explicit file list is given; set to `0` to require explicit paths or the `-a` flag |
**`[info]`** **`[info]`**
| Key | Default | Description | | Key | Default | Description |
@@ -204,7 +245,7 @@ change the default without having to pass flags every time.
### 4.3. Locale shortcuts ### 4.3. Locale shortcuts
The `[general]` key `SET_LOCALE` accepts a comma-separated list of The `[lang]` key `SET_LOCALE` accepts a comma-separated list of
`alias:locale` pairs. Each pair generates a function of that name at startup: `alias:locale` pairs. Each pair generates a function of that name at startup:
```ini ```ini
@@ -214,6 +255,16 @@ SET_LOCALE = fr:fr_FR.UTF-8, us:en_US.UTF-8
This creates `setfr` and `setus`. Use `setlocale <locale>` to switch to any This creates `setfr` and `setus`. Use `setlocale <locale>` to switch to any
installed locale directly. installed locale directly.
Set `DEFAULT_LANG` to one of the defined aliases to activate that locale
automatically at login:
```ini
DEFAULT_LANG = fr
```
If `DEFAULT_LANG` is set but does not match any alias in `SET_LOCALE`, a
warning is displayed and no locale change is applied.
### 4.4. Prompt theming ### 4.4. Prompt theming
The prompt appearance is controlled by two mechanisms that are applied in order The prompt appearance is controlled by two mechanisms that are applied in order

View File

@@ -1,71 +1,289 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. 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/). 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`). Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
--- ---
## [3.99.1-4_rc_1] — 2026 ## [4.1.0] — 2026-05-07
### Added ### Added
- **Theming system** — `load_theme` in `profile.d/prompt.sh` loads `.theme` - `profile.sh --install` command to automatically configure profile loading in
files from `profile.d/themes/` (or a custom directory set via shell startup files.
`PROMPT_THEME_DIR`). Theme files are **parsed, not executed** — no shell code - `--install --bashrc` and `--install --profile` target selectors for
ever runs from a theme. single-file installation.
- **Built-in themes** — `default`, `dark`, `light`, `solarized` (24-bit - **`git.sh`** — entirely new module providing git workflow helpers: `gst`,
true-colour), `solarized-light` (24-bit), `monokai`, `monochrome`, `abyss`, `ggraph`, `gsync`, `gacp`, `greset`, `gwip`, `gprune`, `groot`.
`plasma`, `adwaita`. - Dedicated git helper completions under `profile.d/bash-completion/`, loaded
- **`[prompt]` section** — `PROMPT_THEME` and `PROMPT_THEME_DIR` keys to select automatically in interactive sessions from `profile.d/bash-completion/*.sh`.
a theme; eleven `PROMPT_COLOR_*` keys for per-key overrides in `profile.conf`.
- **Standard colour variables as theme keys** — theme files may also override ### Changed
the `disp.sh` colour variables (`Black`, `Blue`, `On_IBlack`, …) to remap the - `disp` now wraps long messages on terminal width, avoids mid-word splits, and
terminal palette used by `ls`, `grep`, and colour-aware tools. aligns continuation lines with the message body after the prefix.
- **Module configuration defaults** — all modules now expose their hardcoded - `help` now supports `help <command>` and delegates to `<command> --help`.
defaults as `profile.conf` keys: `TAZ_*`, `UTAZ_*`, `EXPANDLIST_*`,
`CLEAN_*`, `RMSPC_*`, `FINDBIG_*`, `RAIN_*`, `MATRIX_*`, `SSH_DEFAULT_OPT`, ### Fixed
`GENPWD_*`, `PWDSCORE_*`, `BUSY_*`, `METEO_DEFAULT_CITY`, `DWL_*`, - Startup responsiveness improved: `check_updates -q` now uses a short network
`MYEXTIP_*`, `PKGS_*`, `PPU_*`, `KU_*`, `UPDT_DEFAULT_BRANCH`. timeout so unavailable/slow networks no longer delay prompt readiness.
- **`UPDT_DEFAULT_BRANCH`** — configures the git branch used by `check_updates` - `dwl` gained timeout support (`-t` / `--timeout`) and is now used by quiet
and `profile_upgrade`. Changing the key causes `profile_upgrade` to startup update checks to enforce fast failure.
automatically switch the local checkout to the new branch and display a - `profile.sh` now detects direct execution and warns that it is designed to be
warning. sourced.
- **`doc/` directory** — `CONTRIBUTING.md`, `FAQ.md`, `profile.conf.example`
(annotated template), `todo.md`. ## [4.0.0] — 2026-04-23
- **`.gitignore`** — `profile.conf` is now git-ignored so personal settings are
never accidentally staged. ### Added
- New `profile.conf` reference template at `doc/profile.conf.example`.
### Changed - Dynamic locale shortcuts generated from `SET_LOCALE` and startup default
- README §2 now explains how to create `profile.conf` from language selection through `DEFAULT_LANG`.
`doc/profile.conf.example` (new section 2.1 "Initial configuration"). - Prompt theming system with bundled themes (`default`, `dark`, `light`,
- README §4 updated with full module-defaults tables, theming reference, and a `solarized`, `solarized-light`, `monokai`, `monochrome`, `abyss`, `plasma`,
note about `profile.conf` being git-ignored. `adwaita`) and per-key prompt color overrides.
- Theme values no longer carry the `export` keyword (they are not shell - Module defaults exposed as configuration keys in `profile.conf`.
variables, only data).
### Changed
### Security - `utaz` now supports a wider range of archive formats.
- `load_theme` uses a strict allowlist (no `eval`, no sourcing). Only - Prompt and theme rendering improved, including better 24-bit color support.
`PROMPT_COLOR_*` keys and known `disp.sh` colour variable names are accepted. - Overall code quality and maintainability improved across modules.
Values must match `\$[A-Za-z_][A-Za-z0-9_]*` or `\\e\[[0-9;]*m`; any other
value is discarded with a warning. ### Documentation
- README updated with full function reference and configuration tables.
--- - New and expanded docs in `doc/` (`CONTRIBUTING.md`, `FAQ.md`, `todo.md`).
- Historical releases imported from `history.txt` into this changelog.
---
---
> **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 ## [3.99.2-4_rc_2] — 2026-04-21
> log (`git log --oneline`).
### Fixed
## [3.95.3-4_beta_3] — 2024 - **`prompt.sh`** — `\$Last_Command` in PS1 was escaped, preventing the exit
code from ever appearing in the prompt (the local variable no longer exists
### Added when PS1 is rendered by bash). Removed the backslash so the value is embedded
- Initial public release candidate series. at `set_prompt` build time.
- Core modules: `compress`, `disp`, `filefct`, `fun`, `help`, `info`, `lang`, - **`filefct.sh``file_stats()`** — a stray unconditional `shift` after
`net`, `packages`, `processes`, `prompt`, `pwd`, `rain`, `ssh`, `updates`. `esac` doubled-shifted arguments already shifted by each `case` branch;
- Bar-style prompt with time, command duration, and exit code. successive options such as `-H -d` were silently skipped.
- `taz` / `utaz` archive helpers. - **`packages.sh` `pkgs()`** — replaced the unreliable binary-presence test
- `genpwd` / `pwdscore` password tools. (`command -v dpkg / rpm`) with the new `get_pkgmgr` function. Also corrected
- `matrix` / `rain` screensavers. a typo in the "no package manager" error message (`avialable``available`).
- `profile_upgrade` with git and archive download support. - **`processes.sh``kt()`** — copy-paste error: usage error message read
`"Usage: ppg <string>"` instead of `"Usage: kt <pid>"`.
### Added
- **`packages.sh``get_pkgmgr()`** — new exported helper that detects the
active package manager of the running distribution. Detection first reads
`/etc/os-release` (`ID` then `ID_LIKE`), then falls back to a
fixed-priority binary scan. Supported families: `apt`, `dnf`, `yum`,
`zypper`, `pacman`, `apk`, `portage`, `xbps`, `nix`. Returns 1 when
nothing is identified. Available to all future commands in `packages.sh`.
---
## [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.
---
## [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.
---
> **Note:** The section below was imported from `history.txt` to preserve
> pre-`3.95.x-4_beta` release notes.
## Legacy releases (imported from `history.txt`)
### [3.6.1] — 2026-03-05
- Fix typo in `compress.sh`.
### [3.6.0] — 2026-03-05
- Improved `utaz` with broader multi-format support.
- Introduced `ppu` and `ppn`.
- Improved update system.
### [3.5.0] — 2026-03-04
- `rain` now has configurable speed and color.
- `showinfo` adapted to `fastfetch` (in addition to `neofetch`).
### [3.3.1] — 2022-02-24
- Fixed version detection.
- Added `busy`.
- Fixed use of library functions before loading.
### [3.3.0] — 2022-11-28
- Initial version update support.
- Changed versioning code.
- Added installation path detection.
### [3.2.3] — 2022-11-28
- Improved README.
### [3.2.2] — 2022-11-21
- Fixed `taz` compression level parsing.
- Fixed typo in `dpkgs`.
### [3.2.1] — 2022-11-20
- Fixed several messages.
- Made `dpkgs` RPM-aware (initial support).
- Removed version history from main script and reverted declaration order.
- Added required license information in all files.
- Completed `LICENSE` file.
### [3.2.0] — 2022-11-18
- Created `disp` command and integrated it across the codebase.
### [3.1.1] — 2022-11-10
- `genpwd`: added feasibility check for requested password constraints.
### [3.1.0] — 2022-11-08
- Added password generator.
### [3.0.1] — 2022-11-07
- Added concatenation option to `rmspc`.
- Added `ku`.
- Improved error handling in `meteo`.
### [3.0.0] — 2022-08-27
- Split code into several files/modules.
- Added `rain` screensaver.
### [2.8.2] — 2022-07-29
- Added warning for non-bash users.
### [2.8.1] — 2022-07-19
- Cleanup, fixes and optimizations.
### [2.8.0] — 2022-06-24
- Added `backtrace`, `error` and `settrace`.
- Bugfixes in `showinfo`.
### [2.7.1] — 2022-06-22
- Minor corrections.
- Added `help` command.
### [2.7.0] — 2022-06-21
- Added `isipv4` and `isipv6`, integrated into `rmhost`.
- Removed broken Konsole save/restore support.
### [2.6.3] — 2021-10-18
- Changed PS1 to status-bar style.
- Minor improvements.
### [2.6.2] — 2021-02-26
- Bugfix in `taz` for directories with trailing slash.
### [2.6.1] — 2020-12-25
- Added checks in `rmhost`.
- Improved `rmspc`.
- Created `expandlist`.
### [2.6.0] — 2020-10-24
- Added Konsole session save/restore.
### [2.5.3] — 2020-09-11
- Added aliases, improved code consistency and fixed typos.
- Improved `utaz`, removed `showdiskmap`, removed remaining French text.
- Added license information for future publication.
### [2.5.2] — 2020-03-06
- Sorted and improved aliases.
### [2.5.1] — 2020-03-05
- Language consistency fixes.
- Added `pigz` support in `taz`.
### [2.5.0] — 2020-03-03
- Added `taz` and `rmspc`.
- Renamed `auzip` to `utaz` and improved it.
### [2.4.0] — 2020-03-02
- Added `auzip`.
### [2.3.2] — 2020-01-31
- `figlet`: changed default font to `ansi_shadow`.
### [2.3.1] — 2020-01-16
- Bugfix: non-interactive shells were blocked by some functions.
### [2.3.0] — 2020-01-08
- Added `figlet` and `neofetch` as MOTD replacement.
### [2.2.0] — 2019-12-16
- Added `showinfo`.
- First implementation of `showdiskmap`.
### [2.1.2] — 2019-09-24
- Bugfix in profile version display.
### [2.1.1] — 2019-09-23
- Bugfix in `dpkgs`.
### [2.1.0] — 2018-09-16
- Added `rmhost`, `setc`, `setfr`.
- Improved locale management.
### [2.0.1] — 2017-02-04
- `clean` improvements (`--shell`).
### [2.0.0] — 2015-10-24
- Added advanced functions (`clean`, `ssr`, etc.).
### [1.0.0] — 2013-02-16
- Initial version.
### [Initial fork]
Forked default Bash profile from Beyond Linux From Scratch by
* James Robertson <jameswrobertson@earthlink.net>
* Dagmar d'Surreal <rivyqntzne@pbzpnfg.arg>

View File

@@ -1,171 +1,210 @@
# Contributing to profile # Contributing to profile
Thank you for your interest in contributing. This document explains how to get Thank you for your interest in contributing. This document explains how to get
set up, what the conventions are, and how to submit work. set up, what the conventions are, and how to submit work.
--- ---
## 1. Before you start ## 1. Before you start
- Check the [to-do list](./todo.md) to see if your idea is already planned. - 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) - Check the [issue tracker](https://git.geoffray-levasseur.org/fatalerrors/profile/issues)
to avoid duplicate work. to avoid duplicate work.
- For significant changes, open an issue or contact the maintainer before - For significant changes, open an issue or contact the maintainer before
writing code — alignment on design saves everyone time. writing code — alignment on design saves everyone time.
--- ---
## 2. Getting the source ## 2. Getting the source
A Git clone is mandatory for contributions: A Git clone is mandatory for contributions:
```bash ```bash
git clone https://git.geoffray-levasseur.org/fatalerrors/profile.git git clone https://git.geoffray-levasseur.org/fatalerrors/profile.git
cd profile cd profile
``` ```
Always work from the **latest commit on `master`** (or the branch you intend Always work from the **latest commit on `master`** (or the branch you intend
to target). Stale forks cause avoidable merge conflicts. to target). Stale forks cause avoidable merge conflicts.
--- ---
## 3. Development environment ## 3. Branch policy
| Requirement | Minimum version | Notes | | Branch | Purpose |
|---|---|---| |---|---|
| Bash | 4.3 | Namerefs (`local -n`) required | | `master` | Main development branch — new features and enhancements go here |
| shellcheck | any recent | Run before every commit | | `<version>` (e.g. `3.x`) | Maintenance branch for a released version — bugfixes backported from `master` |
| git | any | For contributing patches |
| bats-core | 1.x | Optional — for running the test suite | **New functionality** must always target `master`.
Install shellcheck: **Bugfixes** must target the branch where the bug was introduced:
```bash - If the bug exists in a released version, open the fix against that version's
# Debian / Ubuntu maintenance branch first, then cherry-pick onto `master`.
apt-get install shellcheck - If the bug is only in `master` (unreleased), fix it directly on `master`.
- During a release-candidate cycle, bugfixes go on the `x.*` branch and are
# Fedora / RHEL merged back into `master` before the final release.
dnf install ShellCheck
Do **not** add new features to a maintenance branch.
# macOS
brew install shellcheck ---
```
## 4. Versioning scheme
---
Versions follow the format **`MAJOR.MINOR.PATCH`** where the `MINOR` number
## 4. Code style conveys the development stage of the next major release:
### General rules | Minor range | Stage | Rules |
- **Bash only** — no external interpreters in core modules. Python or Perl is |---|---|---|
acceptable for completely self-contained, optional utilities that have no | `x.90.y` | **Alpha** toward `x+1` | Stays on `master`. Development is open: new features are welcome, regressions are acceptable. |
dependencies beyond a minimal Debian or CentOS installation. | `x.95.y` | **Beta** toward `x+1` | The `x+1.*` maintenance branch is created at this point. No regression unless absolutely necessary; new features still allowed. |
- **4-space indentation** — no tabs. | `x.99.y` | **RC** toward `x+1` | Bugfixes only. No new features. No regression allowed. Becomes `x+1.0.0` when stable. |
- **`[[ … ]]`** for all conditionals — not `[ … ]`.
- **`(( … ))`** for arithmetic — not `$(( … ))` in conditionals. Examples: `3.90.1` is the first alpha toward `4.0`, `3.99.2` is the second
- **`local`** for all function-internal variables — avoid polluting the release candidate for `4.0`.
environment.
- **`printf`** instead of `echo` wherever the format matters. The `PATCH` number increments freely within a stage. A bump in `MINOR`
- **Never `eval`** — use namerefs (`local -n`), `${!varname}` indirection, or (e.g. `90``95`) always indicates a stage promotion in development phase.
`declare -g` instead.
- **No hardcoded defaults** — wire every configurable value through Any experimental version must have it's dedicated branch.
`${VAR:-default}` and document the key in `profile.conf` and `README.md §4`.
---
### Function conventions
- Public functions **must** be exported: `export -f funcname`. ## 5. Development environment
- Every public function **must** support `-h` / `--help` and print usage to |---|---|---|
stdout, returning 0. | Bash | 4.3 | Namerefs (`local -n`) required |
- Use `getopt` (not `getopts`) for option parsing — it handles long options and | shellcheck | any recent | Run before every commit |
`--` correctly. | git | any | For contributing patches |
- Follow existing error-return conventions: 0 = success, 1 = usage error, | bats-core | 1.x | Optional — for running the test suite |
2 = bad options, 3 = missing dependency, 4+ = runtime failure.
- Prefix all local helper variables with a short unique prefix (e.g. `_taz_`) Install shellcheck:
to prevent collisions with caller-scope variables. ```bash
# Debian / Ubuntu
### Module structure apt-get install shellcheck
Every new module should follow this pattern:
# Fedora / RHEL
```bash dnf install ShellCheck
#!/usr/bin/env bash
# <copyright block identical to existing modules> # macOS
brew install shellcheck
load_conf "<module_name>" ```
# --- functions --- ---
export -f my_function ## 6. Code style
# EOF ### General rules
``` - **Bash only** — no external interpreters in core modules. Python or Perl is
acceptable for completely self-contained, optional utilities that have no
Add the `load_conf` call near the top after any variable declarations. dependencies beyond a minimal Debian or CentOS installation.
- **4-space indentation** — no tabs.
--- - **`[[ … ]]`** for all conditionals — not `[ … ]`.
- **`(( … ))`** for arithmetic — not `$(( … ))` in conditionals.
## 5. Configuration keys - **`local`** for all function-internal variables — avoid polluting the
environment. Prefer upper case for global and lowercase for local.
When adding a configurable default: - **`printf`** instead of `echo` all the time.
- **Never `eval`** — use namerefs (`local -n`), `${!varname}` indirection, or
1. Use `${MY_VAR:-hardcoded_default}` in the function body. `declare -g` instead.
2. Add a commented-out entry with a description to `profile.conf`. - **No hardcoded defaults** — wire every configurable value through
3. Document the key in the matching table in `README.md §4.2`. `${VAR:-default}` and document the key in `profile.conf` and `README.md §4`.
--- ### Function conventions
- Public functions **must** be exported: `export -f funcname`.
## 6. Theming - Every public function **must** support `-h` / `--help` and print usage to
stdout, returning 0.
New theme files go in `profile.d/themes/` with a `.theme` extension. - Use `getopt` (not `getopts`) for option parsing — it handles long options and
They are **parsed, not executed** — do not add shell logic. `--` correctly.
See the existing themes and `README.md §4.4` for the allowed syntax. - 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.
## 7. Running shellcheck
### Module structure
```bash Every new module should follow this pattern:
shellcheck -x profile.sh profile.d/*.sh
``` ```bash
#!/usr/bin/env bash
All warnings must be resolved before a patch will be accepted. Accepted # <copyright block identical to existing modules>
suppression directives (`# shellcheck disable=SCxxxx`) require an inline
comment explaining why the suppression is necessary. load_conf "<module_name>"
--- # --- functions ---
## 8. Submitting a contribution export -f my_function
### Via Git (preferred) # EOF
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)`. Add the `load_conf` call near the top after any variable declarations.
4. Push and open a pull request against `master`.
---
### Via patch
If you do not have push access: ## 7. Configuration keys
```bash
git format-patch origin/master When adding a configurable default:
```
Send the resulting `.patch` file(s) to 1. Use `${MY_VAR:-hardcoded_default}` in the function body.
`fatalerrors <at> geoffray-levasseur <dot> org`. 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`.
### Commit message format
``` ---
module: imperative short description
## 8. Theming
Optional longer explanation of what changed and why. Wrap at 72 characters.
Reference issue numbers if applicable: closes #42. 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.
---
---
## 9. What will be rejected
## 9. Running shellcheck
- Code requiring packages not in a minimal Debian or CentOS install.
- Use of `eval`, `source`-based config loading, or other code-injection vectors. ```bash
- Changes that break Bash 4.3 compatibility. shellcheck -x profile.sh profile.d/*.sh
- Patches without a passing `shellcheck` run. ```
- New functions without `--help` support.
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.
## 10. Financial contributions
---
Contact the maintainer by mail if you wish to make a financial contribution.
## 10. 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.
```
---
## 11. 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.
---
## 12. Financial contributions
Contact the maintainer by mail if you wish to make a financial contribution.

View File

@@ -1,208 +1,320 @@
# Frequently Asked Questions # Frequently Asked Questions
--- ---
## Installation & loading ## Installation & loading
**Q: profile refuses to load and prints "This profile requires Bash 4.3 or higher."** **Q: How do I install profile automatically into my shell startup files?**
Your system's default shell is an older Bash (common on macOS, which ships Run the installer directly (no need to source first):
Bash 3.x for licensing reasons). Install a newer Bash: ```bash
```bash bash <installpath>/profile/profile.sh --install
# macOS ```
brew install bash This appends the required `source` line to both `~/.bashrc` and `~/.profile`.
# then add /opt/homebrew/bin/bash to /etc/shells and chsh To target only one file:
``` ```bash
Or point your terminal emulator at the newer binary explicitly. bash <installpath>/profile/profile.sh --install --bashrc
bash <installpath>/profile/profile.sh --install --profile
--- ```
The operation is idempotent — running it again will not add a duplicate line.
**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 **Q: I ran `profile.sh` directly and got a warning about sourcing.**
scripts start with `#!/usr/bin/env bash`.
profile.sh is designed to be *sourced*, not executed:
--- ```bash
source <installpath>/profile/profile.sh
**Q: I set `PROFILE_PATH` but profile still can't find its modules.** ```
The only exception is `--install`, which must be passed to a direct execution
`PROFILE_PATH` must be exported *before* you source `profile.sh`: (`bash profile.sh --install`) to set up the sourcing line automatically.
```bash
export PROFILE_PATH=/opt/profile ---
source /opt/profile/profile.sh
``` **Q: profile refuses to load and prints "This profile requires Bash 4.3 or higher."**
If set after sourcing, `MYPATH` is already locked in and the variable has
no effect. 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
**Q: Can I load profile system-wide via `/etc/profile`?** brew install bash
# then add /opt/homebrew/bin/bash to /etc/shells and chsh
It is not recommended. User `.bashrc` files frequently set variables that ```
conflict with the aliases and locale functions defined here, leading to Or point your terminal emulator at the newer binary explicitly.
surprising behaviour. Per-user sourcing from `~/.bashrc` is the supported
method. ---
--- **Q: I sourced `profile.sh` but functions are not available in sub-shells or scripts.**
## Configuration 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
**Q: I edited `profile.conf` but my changes have no effect.** scripts start with `#!/usr/bin/env bash`.
`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: I set `PROFILE_PATH` but profile still can't find its modules.**
---
`PROFILE_PATH` must be exported *before* you source `profile.sh`:
**Q: How do I find out which configuration keys a module supports?** ```bash
export PROFILE_PATH=/opt/profile
Every supported key is documented with a comment in `profile.conf`. source /opt/profile/profile.sh
See also `README.md §4.2` for a consolidated table. ```
If set after sourcing, `MYPATH` is already locked in and the variable has
--- no effect.
**Q: A key I set in `profile.conf` is being ignored.** ---
Check that: **Q: Can I load profile system-wide via `/etc/profile`?**
1. The key is inside the correct `[section]` header.
2. There is no leading space before the section name (`[section]` not It is not recommended. User `.bashrc` files frequently set variables that
`[ section ]`). conflict with the aliases and locale functions defined here, leading to
3. The key is not commented out (no leading `#`). surprising behaviour. Per-user sourcing from `~/.bashrc` is the supported
4. The value contains no backticks or `$(…)` — these are stripped by the method.
parser as a security measure.
---
---
## Configuration
## Prompt & theming
**Q: I edited `profile.conf` but my changes have no effect.**
**Q: How do I change the prompt theme?**
`profile.conf` is parsed once per shell session at load time. Open a new
Add to `profile.conf`: terminal (or `exec bash`) to pick up the changes. There is no live-reload.
```ini
[prompt] ---
PROMPT_THEME = dark
``` **Q: How do I find out which configuration keys a module supports?**
Built-in names: `default`, `dark`, `light`, `solarized`, `solarized-light`,
`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`. Every supported key is documented with a comment in `profile.conf`.
See also `README.md §4.2` for a consolidated table.
---
---
**Q: The solarized or solarized-light theme shows wrong colours.**
**Q: A key I set in `profile.conf` is being ignored.**
Those themes use 24-bit / true-colour ANSI sequences (`\e[38;2;R;G;Bm`).
Test your terminal: Check that:
```bash 1. The key is inside the correct `[section]` header.
printf '\e[38;2;38;139;210mTrue colour test\e[0m\n' 2. There is no leading space before the section name (`[section]` not
``` `[ section ]`).
If you see a solid blue word your terminal supports true colour. 3. The key is not commented out (no leading `#`).
If you see garbage or plain text, switch to a 16-colour theme 4. The value contains no backticks or `$(…)` — these are stripped by the
(`dark`, `default`, etc.) or upgrade your terminal emulator. parser as a security measure.
--- ---
**Q: I created a custom theme but `load_theme` emits "key not allowed" warnings.** ## Prompt & theming
Theme files are parsed, not executed. Only `PROMPT_COLOR_*` keys and the **Q: How do I change the prompt theme?**
standard colour variable names from `disp.sh` (`Black`, `Blue`, `On_IBlack`,
…) are accepted. Any other key — including custom variables — is rejected. Add to `profile.conf`:
See `README.md §4.4` for the full list of accepted keys and value forms. ```ini
[prompt]
--- PROMPT_THEME = dark
```
**Q: Can a theme file contain shell logic or `$(…)` command substitutions?** Built-in names: `default`, `dark`, `light`, `solarized`, `solarized-light`,
`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`, but you can create your
No, and intentionally so. Theme files are parsed line-by-line; shell own theme.
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`).
**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`).
## Functions Test your terminal:
```bash
**Q: `meteo` prints "No city specified" even though I set a default.** printf '\e[38;2;38;139;210mTrue colour test\e[0m\n'
```
The key is `METEO_DEFAULT_CITY` (not `DEFAULT_CITY`), and it must be in the If you see a solid blue word your terminal supports true colour.
`[info]` section: If you see garbage or plain text, switch to a 16-colour theme
```ini (`dark`, `default`, etc.) or upgrade your terminal emulator.
[info]
METEO_DEFAULT_CITY = Paris ---
```
**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
**Q: `dwl` fails with "no download tool found".** standard colour variable names from `disp.sh` (`Black`, `Blue`, `On_IBlack`,
…) are accepted. Any other key — including custom variables — is rejected.
`dwl` requires one of `curl`, `wget`, or `fetch` to be installed. See `README.md §4.4` for the full list of accepted keys and value forms.
Install curl:
```bash ---
# Debian / Ubuntu
apt-get install curl **Q: Can a theme file contain shell logic or `$(…)` command substitutions?**
# Fedora / RHEL No, and intentionally so. Theme files are parsed line-by-line; shell
dnf install curl constructs are never evaluated. This is a security boundary — a malicious
``` theme file cannot execute code. Values must be a colour variable reference
Or set `DWL_PREFERRED_TOOL` in `[net]` to whichever tool you have. (`$Blue`) or a raw ANSI escape literal (`\e[0;34m`).
--- ---
**Q: `pkgs` does not find packages I know are installed.** ## Git helpers
`pkgs` delegates to `dpkg -l` (Debian/Ubuntu) or `rpm -qa` (RHEL/Fedora). **Q: What git helper functions does profile provide?**
If your distribution uses a different package manager (pacman, apk, brew …)
it is not yet supported. See `doc/todo.md` for the tracking issue. All git helpers are defined in `profile.d/git.sh` (new in 4.1.0):
--- | Command | Purpose |
|---|---|
**Q: `profile_upgrade` says "no update available" but I know there is one.** | `gst` | Compact status with branch tracking info |
| `ggraph` | Decorated history graph |
`check_updates` compares the content of the remote `version` file against | `gsync` | Fetch and rebase onto upstream |
`$PROFVERSION`. If `UPDT_DEFAULT_BRANCH` in `[updates]` points to a different | `gacp` | Add, commit and push in one command |
branch than your installation, the version files may not match. Check: | `greset` | Reset to upstream, stashing local changes first |
```bash | `gwip` | Quick WIP checkpoint commit |
cat "$MYPATH/version" | `gprune` | Delete merged local branches |
``` | `groot` | Print or cd to repository root |
and make sure `UPDT_DEFAULT_BRANCH` matches the branch you track.
All commands accept `-h` / `--help`.
---
---
## Compatibility
**Q: Tab completion for `gacp` does not show modified files.**
**Q: Some functions misbehave on macOS / Cygwin.**
Profile ships dedicated completions in `profile.d/bash-completion/git-completion.sh`,
Both environments ship non-GNU userland utilities with different flags and loaded automatically in interactive sessions. If completions are missing,
behaviour. profile is primarily developed and tested on Linux (Debian and check that the system git completion is installed:
RHEL families). macOS and Cygwin bugs are low priority; patches that add ```bash
compatibility without breaking Linux support are welcome. # Debian / Ubuntu
apt-get install bash-completion
--- # Fedora / RHEL
dnf install bash-completion
**Q: Can I use profile with ZSH?** ```
When the native git completion helpers are available, `gacp` path completion
Not officially. Blockers include `local -A` (ZSH requires `typeset -A`) and behaves exactly like `git add` (modified files, untracked files, directories).
`local -n` namerefs. A compatibility layer is listed in `doc/todo.md` but
has not been implemented yet. ---
--- **Q: `gacp` says "No files specified" even though I passed `-a`.**
## Miscellaneous The `-a` / `--auto` flag adds all modified files (equivalent to `git add -A`).
The default depends on `GIT_GACP_AUTO_ADD` in `profile.conf`:
**Q: How do I completely disable profile for one session?** ```ini
[git]
```bash GIT_GACP_AUTO_ADD = 1
PROFILE_DISABLED=1 bash --norc ```
``` Set to `1` to make `-a` the default.
Or simply open a shell without sourcing `~/.bashrc` (`bash --norc`).
---
---
## Functions
**Q: How do I report a bug?**
**Q: `meteo` prints "No city specified" even though I set a default.**
Open an issue on the
[Gitea tracker](https://git.geoffray-levasseur.org/fatalerrors/profile/issues) The key is `METEO_DEFAULT_CITY` (not `DEFAULT_CITY`), and it must be in the
or send a mail to `fatalerrors <at> geoffray-levasseur <dot> org` with: `[info]` section:
- The exact command that triggered the bug ```ini
- Your OS and Bash version (`bash --version`) [info]
- The module involved METEO_DEFAULT_CITY = Paris
- Any relevant error output ```
---
**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: How do I limit how long `dwl` waits for a download?**
Use the `-t` / `--timeout` option:
```bash
dwl -t 5 https://example.com/file.txt /tmp/file.txt
```
This sets a 5-second cap on both the connection and the overall transfer.
The timeout is propagated to `curl` (`--max-time` + `--connect-timeout`),
`wget` (`--timeout`), or `fetch` (`-T`) transparently.
---
**Q: The prompt takes a long time to appear when my network is unavailable.**
Fixed in 4.1.0. `check_updates -q` (called at startup) now enforces a
3-second network timeout. If the update server is unreachable the check
fails silently and the prompt appears immediately.
---
**Q: `help` only shows a list of functions. Can I get usage for a specific one?**
Yes — pass the command name as an argument:
```bash
help gacp
help dwl
help taz
```
This calls `<command> --help` and prints the full usage for that function.
---
**Q: `pkgs` does not find packages I know are installed.**
`pkgs` uses `get_pkgmgr` to detect the active package manager and delegates
to the appropriate tool. Supported families: `apt` (Debian/Ubuntu),
`dnf` / `yum` (RHEL/Fedora), `zypper` (openSUSE), `pacman` (Arch),
`apk` (Alpine), `portage` (Gentoo), `xbps` (Void), `nix`, `brew` (macOS).
If your distribution is not detected, run `get_pkgmgr` to see what is
identified, and check that the package manager binary is in your `PATH`.
---
**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

29
doc/LICENSE Executable file
View File

@@ -0,0 +1,29 @@
Copyright 2021-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
This software is distributed under the BSD-3-Clause license with the
following terms and conditions:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,247 +1,267 @@
# profile.conf — example / reference configuration # profile.conf — example / reference configuration
# Copy this file to the profile installation directory as "profile.conf" # Copy this file to the profile installation directory as "profile.conf"
# and uncomment / edit the keys you want to change. # and uncomment / edit the keys you want to change.
# #
# Format: # Format:
# [section_name] — starts a section # [section_name] — starts a section
# key = value — sets a key (whitespace around = is optional) # key = value — sets a key (whitespace around = is optional)
# # comment — line comment # # comment — line comment
# #
# All keys are optional. Sensible defaults apply when unset. # All keys are optional. Sensible defaults apply when unset.
# Values must not contain backticks or $(…) — those are stripped for security. # Values must not contain backticks or $(…) — those are stripped for security.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# ============================================================================== # ==============================================================================
[system] [system]
# Bash history settings # Bash history settings
HISTSIZE=50000 HISTSIZE=50000
HISTFILESIZE=100000 HISTFILESIZE=100000
HISTIGNORE="&:[bf]g:exit" HISTIGNORE="&:[bf]g:exit"
# Default pager # Default pager
PAGER=less PAGER=less
# Terminal colour capability # Terminal colour capability
TERM=xterm-256color TERM=xterm-256color
# ============================================================================== # ==============================================================================
[compress] [compress]
# taz: Default archive format (-f/--format). # taz: Default archive format (-f/--format).
# Supported: lz (default), xz, bz2, gz, lzo, tar, zip, zst # Supported: lz (default), xz, bz2, gz, lzo, tar, zip, zst
#TAZ_DEFAULT_FORMAT=lz #TAZ_DEFAULT_FORMAT=lz
# taz: Number of compression threads (0 = auto-detect CPU count). # taz: Number of compression threads (0 = auto-detect CPU count).
#TAZ_DEFAULT_THREADS=0 #TAZ_DEFAULT_THREADS=0
# taz: Compression level 1 (fast/large) … 9 (slow/small). # taz: Compression level 1 (fast/large) … 9 (slow/small).
#TAZ_DEFAULT_LEVEL=6 #TAZ_DEFAULT_LEVEL=6
# utaz: Delete source archive after successful extraction (0=no, 1=yes). # utaz: Delete source archive after successful extraction (0=no, 1=yes).
#UTAZ_DEFAULT_DELETE=0 #UTAZ_DEFAULT_DELETE=0
# utaz: Subdirectory creation policy. # utaz: Subdirectory creation policy.
# auto — create one only when the archive has multiple top-level entries # auto — create one only when the archive has multiple top-level entries
# always — always extract into a new subdirectory # always — always extract into a new subdirectory
# never — always flatten into the current directory # never — always flatten into the current directory
#UTAZ_DEFAULT_DIR_MODE=auto #UTAZ_DEFAULT_DIR_MODE=auto
# ============================================================================== # ==============================================================================
[debug] [debug]
# (no configurable keys yet) # (no configurable keys yet)
# ============================================================================== # ==============================================================================
[disp] [disp]
# Uncomment to disable ANSI colours in profile's own output messages. # Uncomment to disable ANSI colours in profile's own output messages.
#NO_COLOR=1 #NO_COLOR=1
# ============================================================================== # ==============================================================================
[filefct] [filefct]
# expandlist: Separator between items (default: space). Use \n for newline. # expandlist: Separator between items (default: space). Use \n for newline.
#EXPANDLIST_DEFAULT_SEPARATOR=" " #EXPANDLIST_DEFAULT_SEPARATOR=" "
# clean: Recurse into subdirectories by default (0=no, 1=yes). # clean: Recurse into subdirectories by default (0=no, 1=yes).
#CLEAN_DEFAULT_RECURSIVE=0 #CLEAN_DEFAULT_RECURSIVE=0
# rmspc: Replacement character for spaces in filenames (default: underscore). # rmspc: Replacement character for spaces in filenames (default: underscore).
#RMSPC_DEFAULT_CHAR=_ #RMSPC_DEFAULT_CHAR=_
# findbig: Number of results to display (default: 10). # findbig: Number of results to display (default: 10).
#FINDBIG_DEFAULT_LIMIT=10 #FINDBIG_DEFAULT_LIMIT=10
# ============================================================================== # ==============================================================================
[fun] [fun]
# busy: Hex pattern searched in /dev/urandom hexdump. # busy: Hex pattern searched in /dev/urandom hexdump.
#BUSY_DEFAULT_PATTERN=ca fe #BUSY_DEFAULT_PATTERN=ca fe
# busy: Delay between matched lines in milliseconds (0 = no delay). # busy: Delay between matched lines in milliseconds (0 = no delay).
#BUSY_DEFAULT_DELAY=0 #BUSY_DEFAULT_DELAY=0
# ============================================================================== # ==============================================================================
[info] [git]
# meteo: Default city when no argument is given. Leave unset to require an # Fallback main branch name used when remote HEAD cannot be detected.
# explicit city argument every time. #GIT_MAIN_BRANCH=main
#METEO_DEFAULT_CITY=Paris
# Default remote used by git helper functions.
# ============================================================================== #GIT_DEFAULT_REMOTE=origin
[lang]
# Comma-separated alias:locale pairs. One function is generated per entry. # Prefix used by gwip when generating automatic checkpoint messages.
# Example: SET_LOCALE="fr:fr_FR.UTF-8,us:en_US.UTF-8,es:es_ES.UTF-8" #GIT_WIP_PREFIX=wip
# creates setfr, setus, setes.
#SET_LOCALE=fr:fr_FR.UTF-8,us:en_US.UTF-8 # gacp: Automatically add all modified files (git add -A) when no explicit file
# list is provided. Set to 0 to require explicit file paths or the -a flag.
# ============================================================================== #GIT_GACP_AUTO_ADD=1
[net]
# dwl: Force a specific download tool (curl, wget, fetch). # ==============================================================================
# Unset = auto-detect (curl preferred, then wget, then fetch). [info]
#DWL_PREFERRED_TOOL=curl # meteo: Default city when no argument is given. Leave unset to require an
# explicit city argument every time.
# myextip: API endpoint for external IP lookup. #METEO_DEFAULT_CITY=Paris
# Alternatives: https://ipinfo.io/json, https://ip-api.com/json/
#MYEXTIP_DEFAULT_URL=https://ip-api.com/json/ # ==============================================================================
[lang]
# ============================================================================== # Comma-separated alias:locale pairs. One function is generated per entry.
[packages] # Example: SET_LOCALE="fr:fr_FR.UTF-8,us:en_US.UTF-8,es:es_ES.UTF-8"
# pkgs: Case-insensitive search by default (0=no, 1=yes). # creates setfr, setus, setes.
#PKGS_DEFAULT_IGNORE_CASE=0 #SET_LOCALE=fr:fr_FR.UTF-8,us:en_US.UTF-8
# ============================================================================== # Alias to activate at login. Must match one of the aliases defined in SET_LOCALE above.
[processes] # Example: DEFAULT_LANG=fr → calls setfr at startup.
# ppu: ps output columns (comma-separated ps field names). # Leave unset to keep the system default locale.
#PPU_DEFAULT_FORMAT=pid,user,%cpu,%mem,start,time,command #DEFAULT_LANG=fr
# ku: Signal sent when killing a user's processes (without SIG prefix). # ==============================================================================
#KU_DEFAULT_SIGNAL=TERM [net]
# dwl: Force a specific download tool (curl, wget, fetch).
# ============================================================================== # Unset = auto-detect (curl preferred, then wget, then fetch).
[prompt] #DWL_PREFERRED_TOOL=curl
# Name of the prompt theme to load, or an explicit path to a .theme file.
# Built-in themes: default, dark, light, solarized, solarized-light, # myextip: API endpoint for external IP lookup.
# monokai, monochrome, abyss, plasma, adwaita # Alternatives: https://ipinfo.io/json, https://ip-api.com/json/
# Solarized variants require a terminal with 24-bit true-colour support. #MYEXTIP_DEFAULT_URL=https://ip-api.com/json/
#PROMPT_THEME=default
# ==============================================================================
# Directory searched for bare theme names. Defaults to profile.d/themes/. [packages]
#PROMPT_THEME_DIR=/path/to/my/themes # pkgs: Case-insensitive search by default (0=no, 1=yes).
#PKGS_DEFAULT_IGNORE_CASE=0
# 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). [processes]
# # ppu: ps output columns (comma-separated ps field names).
# Clock segment #PPU_DEFAULT_FORMAT=pid,user,%cpu,%mem,start,time,command
#PROMPT_COLOR_TIME_FG=$Blue
#PROMPT_COLOR_TIME_BG=$On_IBlack # ku: Signal sent when killing a user's processes (without SIG prefix).
# #KU_DEFAULT_SIGNAL=TERM
# Main bar background
#PROMPT_COLOR_BAR_BG=$On_Blue # ==============================================================================
# [prompt]
# Exit-code segment — success # Name of the prompt theme to load, or an explicit path to a .theme file.
#PROMPT_COLOR_OK_FG=$White # Built-in themes: default, dark, light, solarized, solarized-light,
#PROMPT_COLOR_OK_MARK=$Green # monokai, monochrome, abyss, plasma, adwaita
# # Solarized variants require a terminal with 24-bit true-colour support.
# Exit-code segment — failure #PROMPT_THEME=default
#PROMPT_COLOR_ERR_BG=$On_Red
#PROMPT_COLOR_ERR_FG=$White # Directory searched for bare theme names. Defaults to profile.d/themes/.
#PROMPT_COLOR_ERR_MARK=$BYellow #PROMPT_THEME_DIR=/path/to/my/themes
#
# User / host # Individual colour overrides — these always win over the loaded theme.
#PROMPT_COLOR_ROOT_FG=$Red # Values must be colour variable names from disp.sh (e.g. $Blue, $On_IBlack)
#PROMPT_COLOR_USER_FG=$Green # or raw ANSI escape sequences (e.g. \e[0;34m).
# #
# Working directory # Clock segment
#PROMPT_COLOR_DIR_FG=$ICyan #PROMPT_COLOR_TIME_FG=$Blue
#PROMPT_COLOR_TIME_BG=$On_IBlack
# ============================================================================== #
[pwd] # Main bar background
# genpwd: Default password length. #PROMPT_COLOR_BAR_BG=$On_Blue
#GENPWD_DEFAULT_LENGTH=16 #
# Exit-code segment — success
# genpwd: Maximum occurrences of any single character. #PROMPT_COLOR_OK_FG=$White
#GENPWD_DEFAULT_OCCURS=2 #PROMPT_COLOR_OK_MARK=$Green
#
# genpwd: Number of passwords generated per invocation. # Exit-code segment — failure
#GENPWD_DEFAULT_COUNT=1 #PROMPT_COLOR_ERR_BG=$On_Red
#PROMPT_COLOR_ERR_FG=$White
# genpwd: Include symbols (1=yes, 0=no). #PROMPT_COLOR_ERR_MARK=$BYellow
#GENPWD_DEFAULT_SYMBOLS=1 #
# User / host
# genpwd: Include uppercase letters (1=yes, 0=no). #PROMPT_COLOR_ROOT_FG=$Red
#GENPWD_DEFAULT_UPPERCASE=1 #PROMPT_COLOR_USER_FG=$Green
#
# genpwd: Include lowercase letters (1=yes, 0=no). # Working directory
#GENPWD_DEFAULT_LOWERCASE=1 #PROMPT_COLOR_DIR_FG=$ICyan
# genpwd: Include digits (1=yes, 0=no). # ==============================================================================
#GENPWD_DEFAULT_NUMBERS=1 [pwd]
# genpwd: Default password length.
# pwdscore: Show verbose breakdown by default (1=yes, 0=no). #GENPWD_DEFAULT_LENGTH=16
#PWDSCORE_DEFAULT_VERBOSE=0
# genpwd: Maximum occurrences of any single character.
# ============================================================================== #GENPWD_DEFAULT_OCCURS=2
[rain]
# rain: Falling speed — integer/100 gives seconds (5 → 0.05 s). # genpwd: Number of passwords generated per invocation.
# Values < 1 are used as raw seconds. #GENPWD_DEFAULT_COUNT=1
#RAIN_DEFAULT_SPEED=5
# genpwd: Include symbols (1=yes, 0=no).
# rain: Colour theme. Supported: white (default), green, blue, red, yellow, cyan #GENPWD_DEFAULT_SYMBOLS=1
#RAIN_DEFAULT_COLOR=white
# genpwd: Include uppercase letters (1=yes, 0=no).
# matrix: Falling speed. #GENPWD_DEFAULT_UPPERCASE=1
#MATRIX_DEFAULT_SPEED=3.5
# genpwd: Include lowercase letters (1=yes, 0=no).
# matrix: Colour theme. Supported: green (default), blue, red, yellow, cyan, white #GENPWD_DEFAULT_LOWERCASE=1
#MATRIX_DEFAULT_COLOR=green
# genpwd: Include digits (1=yes, 0=no).
# matrix: Character set. Supported: binary (default), kana, ascii #GENPWD_DEFAULT_NUMBERS=1
#MATRIX_DEFAULT_CHARSET=binary
# pwdscore: Show verbose breakdown by default (1=yes, 0=no).
# ============================================================================== #PWDSCORE_DEFAULT_VERBOSE=0
[ssh]
# ssr: Default SSH options prepended to every ssr call. # ==============================================================================
# Examples: [rain]
# SSH_DEFAULT_OPT=-Y # X11 forwarding # rain: Falling speed — integer/100 gives seconds (5 → 0.05 s).
# SSH_DEFAULT_OPT=-Y -o StrictHostKeyChecking=accept-new # Values < 1 are used as raw seconds.
# SSH_DEFAULT_OPT= # no default options #RAIN_DEFAULT_SPEED=5
#SSH_DEFAULT_OPT=-Y
# rain: Colour theme. Supported: white (default), green, blue, red, yellow, cyan
# ============================================================================== #RAIN_DEFAULT_COLOR=white
[updates]
# Git branch used for update checks and profile_upgrade. # matrix: Falling speed.
# Changing this causes profile_upgrade to automatically switch the local #MATRIX_DEFAULT_SPEED=3.5
# checkout to the new branch on the next run and display a warning.
#UPDT_DEFAULT_BRANCH=master # matrix: Colour theme. Supported: green (default), blue, red, yellow, cyan, white
#MATRIX_DEFAULT_COLOR=green
# ==============================================================================
[general] # matrix: Character set. Supported: binary (default), kana, ascii
# General-purpose section — set any environment variable you need globally. #MATRIX_DEFAULT_CHARSET=binary
# Good place for compilation flags, personal PATH additions, etc.
#CFLAGS=-O2 -pipe -march=native # ==============================================================================
#CXXFLAGS=$CFLAGS [ssh]
#MAKEFLAGS=-j4 # ssr: Default SSH options prepended to every ssr call.
#PKGSOURCES=/usr/local/src # Examples:
# SSH_DEFAULT_OPT=-Y # X11 forwarding
# ============================================================================== # SSH_DEFAULT_OPT=-Y -o StrictHostKeyChecking=accept-new
[aliases] # SSH_DEFAULT_OPT= # no default options
# Command aliases loaded for interactive shells only. #SSH_DEFAULT_OPT=-Y
# 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. # ==============================================================================
# [updates]
# ls # Git branch used for update checks and profile_upgrade.
ll=ls -laFh --color=auto # Changing this causes profile_upgrade to automatically switch the local
la=ls -Ah --color=auto # checkout to the new branch on the next run and display a warning.
l=ls -CF --color=auto #UPDT_DEFAULT_BRANCH=master
ls=ls --color=auto
# # ==============================================================================
# grep [general]
grep=grep --color=auto # General-purpose section — set any environment variable you need globally.
egrep=egrep --color=auto # Good place for compilation flags, personal PATH additions, etc.
fgrep=fgrep --color=auto #CFLAGS=-O2 -pipe -march=native
# #CXXFLAGS=$CFLAGS
# disk usage #MAKEFLAGS=-j4
df=df -H #PKGSOURCES=/usr/local/src
du=du -ch
# # ==============================================================================
# make shortcuts [aliases]
#mk=make # Command aliases loaded for interactive shells only.
#mkin=make install # 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.
# End of profile.conf.example #
# 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

View File

@@ -1,121 +1,114 @@
# profile — to-do list # profile — to-do list
Items marked **[easy]**, **[medium]**, or **[hard]** give a rough effort hint. Items marked **[easy]**, **[medium]**, or **[hard]** give a rough effort hint.
Items marked **[breaking]** would change existing behaviour and require a Items marked **[breaking]** would change existing behaviour and require a
version-bump. version-bump.
--- ---
## Shell / compatibility ## Shell / compatibility
- [ ] **ZSH compatibility layer** — most functions work already; the remaining - [ ] **ZSH compatibility layer** — most functions work already; the remaining
blockers are `local -A` (no associative arrays in ZSH without `typeset -A`) 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 and `local -n` namerefs. A thin compatibility shim would open the project to
ZSH users. **[hard]** ZSH users. **[hard]**
- [ ] **Bash completion** — add a `profile.d/completion/` directory and write - [ ] **Bash completion** — add a more bash completion directory and write
`_profile_upgrade`, `_taz`, `_utaz`, `_meteo`, etc. completions so that `_profile_upgrade`, `_taz`, `_utaz`, `_meteo`, etc. completions so that
`<Tab>` works on all public functions. **[medium]** `<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
## Prompt & theming indicator) in the PS1 bar when inside a Git repository. Should be
gated behind a `[prompt]` config key so it can be disabled. **[medium]**
- [ ] **Git branch in prompt** — show the current branch name (and dirty - [ ] **Virtual-env / conda indicator** — detect `$VIRTUAL_ENV` / `$CONDA_DEFAULT_ENV`
indicator) in the PS1 bar when inside a Git repository. Should be and display the name in the prompt bar. **[easy]**
gated behind a `[prompt]` config key so it can be disabled. **[medium]** - [ ] **True-colour terminal auto-detection** — query `$COLORTERM` and
- [ ] **Virtual-env / conda indicator** — detect `$VIRTUAL_ENV` / `$CONDA_DEFAULT_ENV` `$TERM` at load time; automatically fall back from a 24-bit theme to its
and display the name in the prompt bar. **[easy]** 16-colour equivalent when the terminal does not support true colour. **[medium]**
- [ ] **True-colour terminal auto-detection** — query `$COLORTERM` and - [ ] **True-colour variants of other themes** — create `monokai-tc.theme`,
`$TERM` at load time; automatically fall back from a 24-bit theme to its `abyss-tc.theme`, etc. using the same `\e[38;2;R;G;Bm` approach as the
16-colour equivalent when the terminal does not support true colour. **[medium]** Solarized themes. **[easy]** _(per theme)_
- [ ] **True-colour variants of other themes** — create `monokai-tc.theme`, - [ ] **Theme preview command** — add a `theme_preview` (or `profile_theme`)
`abyss-tc.theme`, etc. using the same `\e[38;2;R;G;Bm` approach as the function that renders a colour swatch and a sample prompt line for the
Solarized themes. **[easy]** _(per theme)_ currently loaded theme, so users can evaluate themes without reloading
- [ ] **Theme preview command** — add a `theme_preview` (or `profile_theme`) the session. **[medium]**
function that renders a colour swatch and a sample prompt line for the - [ ] **`load_theme` — DEFAULTCOL rebuild** — after overriding `DEFAULTFG` and
currently loaded theme, so users can evaluate themes without reloading `DEFAULTBG`, automatically recompute `DEFAULTCOL` from the new values instead
the session. **[medium]** of requiring the theme file to set it explicitly. **[easy]**
- [ ] **`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
## Module improvements - [ ] **`taz` progress bar** — show a `pv` / `dd`-based progress indicator when
compressing large trees, gated behind a `-p` flag. **[medium]**
### compress - [ ] **`utaz` integrity check** — run `tar -tOf` / `unzip -t` / `7z t` before
- [ ] **`taz` progress bar** — show a `pv` / `dd`-based progress indicator when extracting and abort if the archive is corrupt. **[easy]**
compressing large trees, gated behind a `-p` flag. **[medium]**
- [ ] **`utaz` integrity check** — run `tar -tOf` / `unzip -t` / `7z t` before ### filefct
extracting and abort if the archive is corrupt. **[easy]** - [ ] **`findbig` / `findzero` / `finddead``fd` integration** — optionally
use `fd` instead of `find` when available for faster traversal. **[easy]**
### filefct - [ ] **`file_stats` — human-readable totals** — add `--human` flag to emit
- [ ] **`findbig` / `findzero` / `finddead``fd` integration** — optionally sizes in K/M/G instead of bytes. **[easy]**
use `fd` instead of `find` when available for faster traversal. **[easy]**
- [ ] **`file_stats` — human-readable totals** — add `--human` flag to emit ### info
sizes in K/M/G instead of bytes. **[easy]** - [ ] **`showinfo` fallback** — when neither `neofetch` nor `fastfetch` is
installed, print a minimal sysinfo block (hostname, OS, kernel, uptime,
### info CPU, RAM) using pure Bash + `/proc`. **[medium]**
- [ ] **`showinfo` fallback** — when neither `neofetch` nor `fastfetch` is
installed, print a minimal sysinfo block (hostname, OS, kernel, uptime, ### net
CPU, RAM) using pure Bash + `/proc`. **[medium]** - [ ] **`dwl` resume support** — pass `-C -` to curl / `--continue-at -` to
wget for interrupted downloads; gate behind a `-r` flag. **[easy]**
### net - [ ] **`myextip` multiple providers** — fall back to a secondary URL
- [ ] **`dwl` resume support** — pass `-C -` to curl / `--continue-at -` to (configurable via `MYEXTIP_FALLBACK_URL`) when the primary times out.
wget for interrupted downloads; gate behind a `-r` flag. **[easy]** **[easy]**
- [ ] **`myextip` multiple providers** — fall back to a secondary URL
(configurable via `MYEXTIP_FALLBACK_URL`) when the primary times out. ### processes
**[easy]** - [ ] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be
killed without acting. **[easy]**
### packages
- [ ] **Additional backends** — add support for `pacman` (Arch), `apk` (Alpine), ### pwd
`xbps-query` (Void), and `brew` (macOS). **[medium]** - [ ] **`genpwd` passphrase mode** — add `-w` / `--words N` to generate
word-based passphrases (diceware-style) from `/usr/share/dict/words`.
### processes **[medium]**
- [ ] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be
killed without acting. **[easy]** ### ssh
- [ ] **SSH agent management** — add `ssh_agent_start` / `ssh_agent_stop` helpers
### pwd that start a persistent `ssh-agent`, add configured keys, and survive
- [ ] **`genpwd` passphrase mode** — add `-w` / `--words N` to generate re-login via a socket stored in `~/.ssh/agent.env`. **[medium]**
word-based passphrases (diceware-style) from `/usr/share/dict/words`. - [ ] **`rmhost` glob support** — allow `rmhost '*.example.com'` to remove all
**[medium]** matching entries in one call. **[easy]**
### ssh ### updates
- [ ] **SSH agent management** — add `ssh_agent_start` / `ssh_agent_stop` helpers - [ ] **Automatic update check age** — store a timestamp in `~/.cache/profile_last_check`;
that start a persistent `ssh-agent`, add configured keys, and survive skip the network request in `check_updates -q` if the last check was less
re-login via a socket stored in `~/.ssh/agent.env`. **[medium]** than `UPDT_CHECK_INTERVAL` hours ago (configurable, default 24). **[medium]**
- [ ] **`rmhost` glob support** — allow `rmhost '*.example.com'` to remove all - [ ] **Changelog display** — after a successful `profile_upgrade`, fetch and
matching entries in one call. **[easy]** display `CHANGELOG.md` entries newer than the previously installed version.
**[medium]**
### 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]** ## Infrastructure
- [ ] **Changelog display** — after a successful `profile_upgrade`, fetch and
display `CHANGELOG.md` entries newer than the previously installed version. - [ ] **Test suite** — add a `test/` directory with `bats` (Bash Automated
**[medium]** 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`
## Infrastructure and the `bats` suite on every push. **[medium]**
- [ ] **`profile_status` function** — print a diagnostic summary: installed
- [ ] **Test suite**add a `test/` directory with `bats` (Bash Automated version, active theme, loaded modules, detected Bash version, interactive /
Testing System) unit tests for pure functions (`expandlist`, `genpwd`, login shell flags, and `profile.conf` path. **[easy]**
`pwdscore`, `isipv4`, `isipv6`, `parse_conf`, `load_theme`, …). Target for - [ ] **`profile_uninstall` function** — remove the `source` line from
CI. **[hard]** `~/.bashrc` / `~/.profile` and optionally delete the install directory,
- [ ] **CI pipeline** — Gitea Actions (or similar) job that runs `shellcheck` with a dry-run mode. **[medium]**
and the `bats` suite on every push. **[medium]** - [ ] **`disp` syslog integration** — add a `DISP_SYSLOG=1` config key that
- [ ] **`profile_status` function** — print a diagnostic summary: installed additionally pipes E/W messages to `logger`. **[easy]**
version, active theme, loaded modules, detected Bash version, interactive / - [ ] **XDG base-dir support** — honour `$XDG_CONFIG_HOME` as an alternative
login shell flags, and `profile.conf` path. **[easy]** location for `profile.conf` so users can keep `~` tidy. **[medium]**
- [ ] **`profile_uninstall` function** — remove the `source` line from **[breaking]**
`~/.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,147 +0,0 @@
------------------------------------------------------------------------------
Initial version from Beyond Linux From Scratch by
* James Robertson <jameswrobertson@earthlink.net>
* Dagmar d'Surreal <rivyqntzne@pbzpnfg.arg>
------------------------------------------------------------------------------
Current version from Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
------------------------------------------------------------------------------
Version history:
------------------------------------------------------------------------------
# 05/03/2026 v3.6.1
Fix a typo in compress.sh
# 05/03/2026 v3.6.0
Improved utaz to make it multiformat with lot of it
Introduced ppu and ppn
Improved update system
# 04/03/2026 v3.5.0
rain has now configurable speed and color
showinfo adapted to fastfetch, replacing neofetch
# 24/02/2022 v3.3.1
Fixed version detection
Added "busy" function
Fixed use of library functions before it's loaded
# 28/11/2022 v3.3.0
Initial version update support
Changed versioning code
Added installation path detection
# 28/11/2022 v3.2.3
Made proper readme file, to improve
# 21/11/2022 v3.2.2
Fixed taz compression level analysis
Fixed typo in dpkgs
# 20/11/2022 v3.2.1
Fix some messages
Make dpkgs rpm aware (more to come)
Removed version history from main script and revert declaration order
Added required license information in all files
Completed LICENSE file
# 18/11/2022 v3.2.0
Created disp command for display and make use of it
# 10/11/2022 v3.1.1
genpwd: test if password is doable
# 08/11/2022 v3.1.0
Added password generator
# 07/11/2022 v3.0.1
Added concatenation to rmspc
Added ku
Error managed in meteo
# 27/08/2022 v3.0.0
Splitted everything in several files
Added rain screensaver
# 29/07/2022 v2.8.2
Added warning for non bash or zsh users
# 19/07/2022 v2.8.1
Few cleanups, fixes and optimizations
# 24/06/2022 v2.8.0
Added backtrace, error and settrace
[bugfix] corrected showinfo
# 22/06/2022 v2.7.1
[bugfix] few minor corrections
Added help command
# 21/06/2022 v2.7.0
Added isipv4 and isipv6 and use it in rmhost as an improvement
Removed konsole save and restore not working
# 18/10/2021 v2.6.3
Changed PS1 for status bar style version
Few minor improvements
# 26/02/2021 v2.6.2
[bugfix] taz: corrected bug with trailing slash on directories
# 25/12/2020 v2.6.1
Add check on rmhost
Improvements rmspc
Created expendlist
# 24/10/2020 v2.6.0
Added session save and restore for Konsole
# 11/09/2020 v2.5.3
Few more aliases, improved code consistancy and typo,
Improved utaz, removed showdiskmap, removed remaining French,
Added license information for future publication
# 06/03/2020 v2.5.2
Few aliases sorted out
# 05/03/2020 v2.5.1
Language consistancy fix
Added pigz support in taz
# 03/03/2020 v2.5.0
Added command taz and rmspc
Renamed auzip => utaz and improved it
# 02/03/2020 v2.4.0
Added command auzip
# 31/01/2020 v2.3.2
Figlet: changed default font to ansi_shadow
# 16/01/2020 v2.3.1
[bugfix] non-interactive were blocked with some functions
# 08/01/2020 v2.3.0
Added use of figlet and neofetch as a motd replace
# 16/12/2019 v2.2.0
Added showinfo
Primary write of showdiskmap
# 24/09/2019 v2.1.2
[bugfix] bug in profile version display
# 23/09/2019 v2.1.1
[bugfix] dpkgs
# 16/09/2018 v2.1.0
Added rmhost, setc, setfr
More locales management
# 04/02/2017 v2.0.1
clean improvements (--shell)
# 24/10/2015 v2.0.0
Added advanced functionnalities (clean, srr, etc.)
# 16/02/2013 v1.0.0
Initial version

View File

@@ -0,0 +1,220 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Git helper completions for profile.d/git.sh shortcuts.
# ------------------------------------------------------------------------------
# Return 0 when current directory is inside a git work tree.
_profile_git_in_repo()
{
git rev-parse --is-inside-work-tree >/dev/null 2>&1
}
# Load git completion helpers on demand if they are available on the system.
_profile_git_load_completion_helpers()
{
declare -F __git_complete >/dev/null 2>&1 && return 0
local completion_file
for completion_file in \
/usr/share/bash-completion/completions/git \
/usr/share/git/completion/git-completion.bash \
/etc/bash_completion.d/git
do
if [[ -r "$completion_file" ]]; then
# shellcheck source=/dev/null
. "$completion_file"
break
fi
done
declare -F __git_complete >/dev/null 2>&1
}
_profile_git_complete_remotes()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if ! _profile_git_in_repo; then
COMPREPLY=()
return 0
fi
COMPREPLY=( $(compgen -W "$(git remote 2>/dev/null)" -- "$cur") )
}
_profile_git_complete_refs()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if ! _profile_git_in_repo; then
COMPREPLY=()
return 0
fi
COMPREPLY=( $(compgen -W "$(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes refs/tags 2>/dev/null)" -- "$cur") )
}
_profile_git_complete_add_paths()
{
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
local cur words cword prev __git_cmd_idx=0
local complete_opt="--others --modified --directory --no-empty-directory"
if declare -F __git_complete_index_file >/dev/null 2>&1; then
if declare -F _get_comp_words_by_ref >/dev/null 2>&1; then
_get_comp_words_by_ref -n =: cur words cword prev
else
cur="${COMP_WORDS[COMP_CWORD]}"
if (( COMP_CWORD > 0 )); then
prev="${COMP_WORDS[COMP_CWORD-1]}"
else
prev=""
fi
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
cword="$COMP_CWORD"
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
words=("${COMP_WORDS[@]}")
fi
if [[ -n $(__git_find_on_cmdline "-u --update") ]]; then
complete_opt="--modified"
fi
__git_complete_index_file "$complete_opt"
return 0
fi
COMPREPLY=( $(compgen -f -- "${COMP_WORDS[COMP_CWORD]}") )
}
_complete_gst()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
-*)
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
;;
*)
COMPREPLY=( $(compgen -d -- "$cur") )
;;
esac
}
_complete_ggraph()
{
local cur prev
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case "$prev" in
-n|--limit)
COMPREPLY=()
return 0
;;
esac
COMPREPLY=( $(compgen -W "-h --help -n --limit" -- "$cur") )
}
_complete_gsync()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $cur == -* ]]; then
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
return 0
fi
_profile_git_complete_remotes
}
_complete_gacp()
{
local cur prev
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case "$prev" in
-m|--message)
COMPREPLY=()
return 0
;;
esac
if [[ $cur == -* ]]; then
COMPREPLY=( $(compgen -W "-h --help -a --auto -m --message" -- "$cur") )
return 0
fi
_profile_git_complete_add_paths
}
_complete_greset()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $cur == -* ]]; then
COMPREPLY=( $(compgen -W "-h --help -x --with-ignored" -- "$cur") )
return 0
fi
_profile_git_complete_refs
}
_complete_gwip()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $cur == -* ]]; then
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
else
COMPREPLY=()
fi
}
_complete_gprune()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $cur == -* ]]; then
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
return 0
fi
_profile_git_complete_refs
}
_complete_groot()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "-h --help -g --go" -- "$cur") )
}
_profile_git_register_completions()
{
complete -F _complete_gst gst
complete -F _complete_ggraph ggraph
complete -F _complete_gsync gsync
complete -F _complete_gacp gacp
complete -F _complete_greset greset
complete -F _complete_gwip gwip
complete -F _complete_gprune gprune
complete -F _complete_groot groot
}
# Register completions only in interactive bash sessions.
if [[ $- == *i* && -n ${BASH_VERSION:-} ]]; then
_profile_git_load_completion_helpers >/dev/null 2>&1 || true
_profile_git_register_completions
fi
# EOF

View File

@@ -44,36 +44,42 @@
# -n, --no-dir Never create a host directory # -n, --no-dir Never create a host directory
utaz() utaz()
{ {
# shellcheck disable=SC2329
_ununzip() _ununzip()
{ {
unzip -o "$1" -d "$2" >/dev/null 2>&1 unzip -o "$1" -d "$2" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_untar() _untar()
{ {
tar -xf "$1" -C "$2" tar -xf "$1" -C "$2"
} }
# shellcheck disable=SC2329
_ungzip() _ungzip()
{ {
tar -xzf "$1" -C "$2" tar -xzf "$1" -C "$2"
} }
# shellcheck disable=SC2329
_unbzip2() _unbzip2()
{ {
tar -xjf "$1" -C "$2" tar -xjf "$1" -C "$2"
} }
# shellcheck disable=SC2329
_unxz() _unxz()
{ {
tar -xJf "$1" -C "$2" tar -xJf "$1" -C "$2"
} }
# shellcheck disable=SC2329
_unlzop() _unlzop()
{ {
lzop -d "$1" -o "$2/$(basename "${1%.*}")" lzop -d "$1" -o "$2/$(basename "${1%.*}")"
} }
# shellcheck disable=SC2329
_unlzip() _unlzip()
{ {
if command -v plzip >/dev/null 2>&1; then if command -v plzip >/dev/null 2>&1; then
@@ -83,16 +89,19 @@ utaz()
fi fi
} }
# shellcheck disable=SC2329
_ununrar() _ununrar()
{ {
unrar x -o+ "$1" "$2/" >/dev/null 2>&1 unrar x -o+ "$1" "$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_ununarj() _ununarj()
{ {
unarj e "$1" "$2/" >/dev/null 2>&1 unarj e "$1" "$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_unlha() _unlha()
{ {
# lha typically extracts into the current directory # lha typically extracts into the current directory
@@ -100,40 +109,47 @@ utaz()
(cd "$2" && lha -x "../$1") >/dev/null 2>&1 (cd "$2" && lha -x "../$1") >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_ununace() _ununace()
{ {
unace x "$1" "$2/" >/dev/null 2>&1 unace x "$1" "$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_un7z() _un7z()
{ {
7z x "$1" -o"$2/" >/dev/null 2>&1 7z x "$1" -o"$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_unzstd() _unzstd()
{ {
# Zstd decompresses files directly, often requiring tar for archives # Zstd decompresses files directly, often requiring tar for archives
tar --zstd -xf "$1" -C "$2" tar --zstd -xf "$1" -C "$2"
} }
# shellcheck disable=SC2329
_uncpio() _uncpio()
{ {
# CPIO requires careful directory handling # CPIO requires careful directory handling
(cd "$2" && cpio -id < "../$1") >/dev/null 2>&1 (cd "$2" && cpio -id < "../$1") >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_uncabextract() _uncabextract()
{ {
# Requires 'cabextract' package # Requires 'cabextract' package
cabextract "$1" -d "$2/" >/dev/null 2>&1 cabextract "$1" -d "$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_undeb() _undeb()
{ {
# Extracts data content from a Debian package # Extracts data content from a Debian package
dpkg-deb -x "$1" "$2/" >/dev/null 2>&1 dpkg-deb -x "$1" "$2/" >/dev/null 2>&1
} }
# shellcheck disable=SC2329
_unrpm() _unrpm()
{ {
# Extracts CPIO-based payload from an RPM package # Extracts CPIO-based payload from an RPM package
@@ -141,8 +157,9 @@ utaz()
rpm2cpio "$1" | (cd "$2/" && cpio -idmv) >/dev/null 2>&1 rpm2cpio "$1" | (cd "$2/" && cpio -idmv) >/dev/null 2>&1
} }
local PARSED=$(getopt -o hdcn --long help,delete,create-dir,no-dir -n 'utaz' -- "$@") local PARSED
PARSED=$(getopt -o hdcn --long help,delete,create-dir,no-dir -n 'utaz' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
disp E "Invalid options, use \"utaz --help\" to display usage." disp E "Invalid options, use \"utaz --help\" to display usage."
return 1 return 1
@@ -314,10 +331,10 @@ utaz()
fi fi
disp I "Processing archive ${f} with ${extractor}..." disp I "Processing archive ${f} with ${extractor}..."
mkdir -p "${dir}" if ! mkdir -p "${dir}"; then
[[ $? -gt 0 ]] &&
disp E "The filesystem can't create directories, exit!" && disp E "The filesystem can't create directories, exit!" &&
return 1 return 1
fi
${extractor} "${f}" "${dir}" ${extractor} "${f}" "${dir}"
case $? in case $? in
@@ -390,6 +407,7 @@ export -f utaz
# -1, .., -9 Compression level to use [1=fast/biggest, 9=slow/smallest] # -1, .., -9 Compression level to use [1=fast/biggest, 9=slow/smallest]
taz() taz()
{ {
# shellcheck disable=SC2329
_doxz() _doxz()
{ {
command -v xz >/dev/null 2>&1 || { command -v xz >/dev/null 2>&1 || {
@@ -397,17 +415,19 @@ taz()
return 127 return 127
} }
[[ $4 ]] && local verb='-v' local verb=()
[[ $4 ]] && verb=('-v')
# Display a warning for this format # Display a warning for this format
disp W "xz format is not suited for long term archiving." disp W "xz format is not suited for long term archiving."
disp I "See https://www.nongnu.org/lzip/xz_inadequate.html for details." disp I "See https://www.nongnu.org/lzip/xz_inadequate.html for details."
# Compresse to xz (lzma2) - Deprecated # Compress with xz (lzma2) - Deprecated
xz $verb --compress --keep -$3 -T $2 $1 xz "${verb[@]}" --compress --keep "-$3" -T "$2" "$1"
return $? return $?
} }
# shellcheck disable=SC2329
_dolz() _dolz()
{ {
local procopt="--threads $2" local procopt="--threads $2"
@@ -425,13 +445,16 @@ taz()
disp W "Consider installing plzip to obtain multithreading abilities." disp W "Consider installing plzip to obtain multithreading abilities."
} }
[[ $4 ]] && local verb="-vv" local opt=()
[[ $4 ]] && opt=('-vv')
opt+=("$procopt")
# Compresse au format lzip (lzma) # Compress with lzip (lzma)
$command $verb $procopt --keep -$3 $1 $command "${opt[@]}" --keep "-$3" "$1"
return $? return $?
} }
# shellcheck disable=SC2329
_dogz() _dogz()
{ {
local procopt="--processes $2" local procopt="--processes $2"
@@ -449,13 +472,16 @@ taz()
disp W "Consider installing pigz to obtain multithreading abilities." disp W "Consider installing pigz to obtain multithreading abilities."
} }
[[ $4 ]] && local verb="--verbose" local opt=()
[[ $4 ]] && opt=('--verbose')
opt+=("$procopt")
# Compresse au format bz2 # Compress with gzip
$command $verb $procopt --keep -$3 $1 $command "${opt[@]}" --keep "-$3" "$1"
return $? return $?
} }
# shellcheck disable=SC2329
_dobz2() _dobz2()
{ {
local procopt="-p$2" local procopt="-p$2"
@@ -473,13 +499,16 @@ taz()
disp W "Consider installing pbzip2 to obtain multithreading abilities." disp W "Consider installing pbzip2 to obtain multithreading abilities."
} }
[[ $4 ]] && local verb="-v" local opt=()
[[ $4 ]] && opt=('-v')
opt+=("$procopt")
# Compresse au format bz2 # Compress with bz2
$command $verb --compress $procopt --keep -$3 $1 $command "${opt[@]}" --compress --keep "-$3" "$1"
return $? return $?
} }
# shellcheck disable=SC2329
_dolzo() _dolzo()
{ {
command -v lzop >/dev/null 2>&1 || { command -v lzop >/dev/null 2>&1 || {
@@ -487,16 +516,18 @@ taz()
return 127 return 127
} }
[[ $4 ]] && local verb='-v' local verb=()
[[ $4 ]] && verb=('-v')
[[ $2 -gt 1 ]] && disp W "lzop doesn't support multithreading, falling back to 1 thread." [[ $2 -gt 1 ]] && disp W "lzop doesn't support multithreading, falling back to 1 thread."
# Compresse au format lzo # Compress with lzo
lzop --keep -$3 $1 lzop "${verb[@]}" --keep "-$3" "$1"
return $? return $?
} }
local PARSED local PARSED
PARSED=$(getopt -o hdf:p:vq123456789 --long help,delete,format:,parallel:,verbose,quiet --name "taz" -- "$@") PARSED=$(getopt -o hdf:p:vq123456789 --long help,delete,format:,parallel:,verbose,quiet --name "taz" -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
disp E "Invalid options, use \"taz --help\" to display usage." disp E "Invalid options, use \"taz --help\" to display usage."
return 1 return 1
@@ -587,8 +618,7 @@ taz()
if [[ -d "$item" ]]; then if [[ -d "$item" ]]; then
disp I "\t Creating $item.tar... " disp I "\t Creating $item.tar... "
tar -cf "$item.tar" "$item" if ! tar -cf "$item.tar" "$item"; then
if [[ ! $? -eq 0 ]]; then
disp E "tar file creation failed, skipping to next item." disp E "tar file creation failed, skipping to next item."
continue continue
fi fi
@@ -602,8 +632,9 @@ taz()
# Skip compression part if tar is asked # Skip compression part if tar is asked
if [[ $compform != "tar" ]]; then if [[ $compform != "tar" ]]; then
disp I "\t Compressing archive..." disp I "\t Compressing archive..."
_do$compform "$fname" "$nproc" "$complevel" "$verbose" local exec_code=0
[[ ! $? -eq 0 ]] && case $? in "_do$compform" "$fname" "$nproc" "$complevel" "$verbose" || exec_code=$?
[[ ! $exec_code -eq 0 ]] && case $exec_code in
127) 127)
disp E "Compression program unavailable, aborting." disp E "Compression program unavailable, aborting."
return 127 return 127

View File

@@ -70,6 +70,7 @@ settrace()
local PARSED local PARSED
PARSED=$(getopt -oh --long help,on,off,status,force -- "$@") PARSED=$(getopt -oh --long help,on,off,status,force -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"settrace --help\" to display usage." disp E "Invalid options, use \"settrace --help\" to display usage."
return 1 return 1

View File

@@ -36,81 +36,85 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Color definitions # Color definitions
# Standard 16 colors display declaration set_colors()
export DEFAULTFG='\e[0;39m' {
export DEFAULTBG='\e[0;49m' # Standard 16 colors display declaration
export DEFAULTCOL="${DEFAULTBG}${DEFAULTFG}" export DEFAULTFG='\e[0;39m'
export RESETCOL=$'\e[0m' export DEFAULTBG='\e[0;49m'
export DEFAULTCOL="${DEFAULTBG}${DEFAULTFG}"
export RESETCOL=$'\e[0m'
# Regular Colors # Regular Colors
export Black='\e[0;30m' export Black='\e[0;30m'
export Red='\e[0;31m' export Red='\e[0;31m'
export Green='\e[0;32m' export Green='\e[0;32m'
export Yellow='\e[0;33m' export Yellow='\e[0;33m'
export Blue='\e[0;34m' export Blue='\e[0;34m'
export Purple='\e[0;35m' export Purple='\e[0;35m'
export Cyan='\e[0;36m' export Cyan='\e[0;36m'
export White='\e[0;37m' export White='\e[0;37m'
# Bold # Bold
export BBlack='\e[1;30m' export BBlack='\e[1;30m'
export BRed='\e[1;31m' export BRed='\e[1;31m'
export BGreen='\e[1;32m' export BGreen='\e[1;32m'
export BYellow='\e[1;33m' export BYellow='\e[1;33m'
export BBlue='\e[1;34m' export BBlue='\e[1;34m'
export BPurple='\e[1;35m' export BPurple='\e[1;35m'
export BCyan='\e[1;36m' export BCyan='\e[1;36m'
export BWhite='\e[1;37m' export BWhite='\e[1;37m'
# Underline # Underline
export UBlack='\e[4;30m' export UBlack='\e[4;30m'
export URed='\e[4;31m' export URed='\e[4;31m'
export UGreen='\e[4;32m' export UGreen='\e[4;32m'
export UYellow='\e[4;33m' export UYellow='\e[4;33m'
export UBlue='\e[4;34m' export UBlue='\e[4;34m'
export UPurple='\e[4;35m' export UPurple='\e[4;35m'
export UCyan='\e[4;36m' export UCyan='\e[4;36m'
export UWhite='\e[4;37m' export UWhite='\e[4;37m'
# Background # Background
export On_Black='\e[40m' export On_Black='\e[40m'
export On_Red='\e[41m' export On_Red='\e[41m'
export On_Green='\e[42m' export On_Green='\e[42m'
export On_Yellow='\e[43m' export On_Yellow='\e[43m'
export On_Blue='\e[44m' export On_Blue='\e[44m'
export On_Purple='\e[45m' export On_Purple='\e[45m'
export On_Cyan='\e[46m' export On_Cyan='\e[46m'
export On_White='\e[47m' export On_White='\e[47m'
# High Intensity # High Intensity
export IBlack='\e[0;90m' export IBlack='\e[0;90m'
export IRed='\e[0;91m' export IRed='\e[0;91m'
export IGreen='\e[0;92m' export IGreen='\e[0;92m'
export IYellow='\e[0;93m' export IYellow='\e[0;93m'
export IBlue='\e[0;94m' export IBlue='\e[0;94m'
export IPurple='\e[0;95m' export IPurple='\e[0;95m'
export ICyan='\e[0;96m' export ICyan='\e[0;96m'
export IWhite='\e[0;97m' export IWhite='\e[0;97m'
# Bold High Intensity # Bold High Intensity
export BIBlack='\e[1;90m' export BIBlack='\e[1;90m'
export BIRed='\e[1;91m' export BIRed='\e[1;91m'
export BIGreen='\e[1;92m' export BIGreen='\e[1;92m'
export BIYellow='\e[1;93m' export BIYellow='\e[1;93m'
export BIBlue='\e[1;94m' export BIBlue='\e[1;94m'
export BIPurple='\e[1;95m' export BIPurple='\e[1;95m'
export BICyan='\e[1;96m' export BICyan='\e[1;96m'
export BIWhite='\e[1;97m' export BIWhite='\e[1;97m'
# High Intensity backgrounds # High Intensity backgrounds
export On_IBlack='\e[0;100m' export On_IBlack='\e[0;100m'
export On_IRed='\e[0;101m' export On_IRed='\e[0;101m'
export On_IGreen='\e[0;102m' export On_IGreen='\e[0;102m'
export On_IYellow='\e[0;103m' export On_IYellow='\e[0;103m'
export On_IBlue='\e[0;104m' export On_IBlue='\e[0;104m'
export On_IPurple='\e[0;105m' export On_IPurple='\e[0;105m'
export On_ICyan='\e[0;106m' export On_ICyan='\e[0;106m'
export On_IWhite='\e[0;107m' export On_IWhite='\e[0;107m'
}
export -f set_colors
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -124,52 +128,107 @@ export On_IWhite='\e[0;107m'
# D : debug (cyan) # D : debug (cyan)
disp() disp()
{ {
_disp_print_wrapped()
{
local prefix="$1"
local prefix_len="$2"
local target_fd="$3"
shift 3
local message="$*"
local cols="${COLUMNS:-}"
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
cols=$(tput cols 2>/dev/null)
fi
[[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]] && cols=80
local indent_len=0
[[ "$prefix_len" =~ ^[0-9]+$ && "$prefix_len" -gt 0 ]] && indent_len=$((prefix_len + 1))
local width=$((cols - indent_len))
(( width < 10 )) && width=10
local wrapped
wrapped=$(printf "%s" "$message" | fold -s -w "$width")
local first_line=1
local line
while IFS= read -r line || [[ -n "$line" ]]; do
if (( first_line )); then
if [[ -n "$prefix" ]]; then
if [[ "$target_fd" -eq 2 ]]; then
printf "%b\n" "${prefix} ${line}${RESETCOL}" >&2
else
printf "%b\n" "${prefix} ${line}${RESETCOL}"
fi
else
if [[ "$target_fd" -eq 2 ]]; then
printf "%b\n" "${line}${RESETCOL}" >&2
else
printf "%b\n" "${line}${RESETCOL}"
fi
fi
first_line=0
else
if [[ "$target_fd" -eq 2 ]]; then
printf "%*s%b\n" "$indent_len" "" "${line}${RESETCOL}" >&2
else
printf "%*s%b\n" "$indent_len" "" "${line}${RESETCOL}"
fi
fi
done <<< "$wrapped"
}
# Handle NO_COLOR: disable colors if set # Handle NO_COLOR: disable colors if set
local color_enabled=1 local color_enabled=1
[[ -n $NO_COLOR ]] && color_enabled=0 [[ -n $NO_COLOR ]] && color_enabled=0
case ${1^^} in case ${1^^} in
"I") "I")
local heads_plain="[ info ]"
if [[ $color_enabled -eq 1 ]]; then if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IGreen}info${DEFAULTFG} ]" local heads="[ ${IGreen}info${DEFAULTFG} ]"
else else
local heads="[ info ]" local heads="$heads_plain"
fi fi
shift shift
[[ -z $QUIET || $QUIET -ne 1 ]] && \ [[ -z $QUIET || $QUIET -ne 1 ]] && \
printf "%b\n" "${heads} $*${RESETCOL}" _disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*"
;; ;;
"W") "W")
local heads_plain="[ Warning ]"
if [[ $color_enabled -eq 1 ]]; then if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IYellow}Warning${DEFAULTFG} ]" local heads="[ ${IYellow}Warning${DEFAULTFG} ]"
else else
local heads="[ Warning ]" local heads="$heads_plain"
fi fi
shift shift
printf "%b\n" "${heads} $*${RESETCOL}" >&2 _disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*"
;; ;;
"E") "E")
local heads_plain="[ ERROR ]"
if [[ $color_enabled -eq 1 ]]; then if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IRed}ERROR${DEFAULTFG} ]" local heads="[ ${IRed}ERROR${DEFAULTFG} ]"
else else
local heads="[ ERROR ]" local heads="$heads_plain"
fi fi
shift shift
printf "%b\n" "${heads} $*${RESETCOL}" >&2 _disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*"
;; ;;
"D") "D")
local heads_plain="[ debug ]"
if [[ $color_enabled -eq 1 ]]; then if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${ICyan}debug${DEFAULTFG} ]" local heads="[ ${ICyan}debug${DEFAULTFG} ]"
else else
local heads="[ debug ]" local heads="$heads_plain"
fi fi
shift shift
[[ -n $DEBUG && $DEBUG -gt 1 ]] && \ [[ -n $DEBUG && $DEBUG -gt 1 ]] && \
printf "%b\n" "${heads} $*${RESETCOL}" _disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*"
;; ;;
* ) * )
[[ -z $QUIET || $QUIET -ne 1 ]] && \ [[ -z $QUIET || $QUIET -ne 1 ]] && \
printf "%b\n" "$*" _disp_print_wrapped "" 0 1 "$*"
;; ;;
esac esac
} }
@@ -179,5 +238,6 @@ export -f disp
# Load disp section variables # Load disp section variables
load_conf disp load_conf disp
set_colors
# EOF # EOF

View File

@@ -41,8 +41,8 @@ expandlist()
{ {
local separator="${EXPANDLIST_DEFAULT_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' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"expandlist --help\" to display usage." disp E "Invalid options, use \"expandlist --help\" to display usage."
return 1 return 1
@@ -87,6 +87,7 @@ expandlist()
# True glob expansion when wildcards are present. # True glob expansion when wildcards are present.
if [[ "$item" == *'*'* || "$item" == *'?'* || "$item" == *'['* ]]; then if [[ "$item" == *'*'* || "$item" == *'?'* || "$item" == *'['* ]]; then
# shellcheck disable=SC2206 # We actually want the word splitting
expanded=( $item ) expanded=( $item )
else else
expanded=( "$item" ) expanded=( "$item" )
@@ -127,7 +128,7 @@ clean()
# Define short and long options # Define short and long options
local PARSED local PARSED
PARSED=$(getopt -o hrsf --long help,recurs,shell,force -n 'clean' -- "$@") PARSED=$(getopt -o hrsf --long help,recurs,shell,force -n 'clean' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"clean --help\" to display usage." disp E "Invalid options, use \"clean --help\" to display usage."
return 1 return 1
@@ -215,10 +216,14 @@ mcd()
disp E "Missing parameter. Use \"mcd --help\" to display usage." disp E "Missing parameter. Use \"mcd --help\" to display usage."
return 1 return 1
fi fi
mkdir -pv "$1" && cd "$1" || { if ! mkdir -pv "$1"; then
printf "Failed create and/or change directory.\n" disp E "Failed to create directory \"$1\"."
return 1 return 1
} fi
if ! cd "$1"; then
disp E "Failed to change to directory \"$1\"."
return 1
fi
} }
export -f mcd export -f mcd
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -241,6 +246,7 @@ rmspc()
local PARSED local PARSED
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@") PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"rmspc --help\" to display usage." disp E "Invalid options, use \"rmspc --help\" to display usage."
return 1 return 1
@@ -359,7 +365,7 @@ file_stats()
# Short: H, d, m, M, c, t, a, x:, X: # Short: H, d, m, M, c, t, a, x:, X:
# Long: human, details, average, median, count, total, all, ext:, ext-list:, min:, max:, help # Long: human, details, average, median, count, total, all, ext:, ext-list:, min:, max:, help
PARSED=$(getopt -o HdmMctax:X:h --long human,details,average,median,count,total,all,ext:,ext-list:,min:,max:,help -n 'file_stats' -- "$@") PARSED=$(getopt -o HdmMctax:X:h --long human,details,average,median,count,total,all,ext:,ext-list:,min:,max:,help -n 'file_stats' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"file_stats --help\" to display usage." disp E "Invalid options, use \"file_stats --help\" to display usage."
return 1 return 1
@@ -441,7 +447,6 @@ file_stats()
return 1 return 1
;; ;;
esac esac
shift
done done
[[ -n "$1" ]] && path="$1" [[ -n "$1" ]] && path="$1"
@@ -578,6 +583,7 @@ findbig()
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' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"findbig --help\" to display usage." disp E "Invalid options, use \"findbig --help\" to display usage."
return 1 return 1
@@ -660,6 +666,7 @@ findzero()
local PARSED local PARSED
# o: options, long: long equivalents # o: options, long: long equivalents
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'findzero' -- "$@") PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'findzero' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"findzero --help\" to display usage." disp E "Invalid options, use \"findzero --help\" to display usage."
return 1 return 1
@@ -733,6 +740,7 @@ finddead()
local PARSED local PARSED
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@") PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"finddead --help\" to display usage." disp E "Invalid options, use \"finddead --help\" to display usage."
return 1 return 1

View File

@@ -48,6 +48,7 @@ busy()
# Short: h, p:, d: # Short: h, p:, d:
# Long: help, pattern:, delay: # Long: help, pattern:, delay:
PARSED=$(getopt -o hp:d: --long help,pattern:,delay: -n 'busy' -- "$@") PARSED=$(getopt -o hp:d: --long help,pattern:,delay: -n 'busy' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"busy --help\" to display usage." disp E "Invalid options, use \"busy --help\" to display usage."
return 1 return 1
@@ -89,7 +90,8 @@ busy()
done done
# Convert milliseconds to seconds for 'sleep' # Convert milliseconds to seconds for 'sleep'
local delay_s=$(awk "BEGIN{ local delay_s
delay_s=$(awk "BEGIN{
printf \"%.3f\", $delay_ms / 1000 }") printf \"%.3f\", $delay_ms / 1000 }")
# Monitor /dev/urandom # Monitor /dev/urandom

613
profile.d/git.sh Executable file
View File

@@ -0,0 +1,613 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
# * with or without modification, are permitted provided
# * that the following conditions are met:
# *
# * Redistributions of source code must retain the above
# * copyright notice, this list of conditions and the
# * following disclaimer.
# *
# * Redistributions in binary form must reproduce the above
# * copyright notice, this list of conditions and the following
# * disclaimer in the documentation and/or other materials
# * provided with the distribution.
# *
# * Neither the name of the copyright holder nor the names
# * of any other contributors may be used to endorse or
# * promote products derived from this software without
# * specific prior written permission.
# *
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Built-in defaults (can be overridden from [git] section in profile.conf)
: "${GIT_MAIN_BRANCH:=main}"
: "${GIT_DEFAULT_REMOTE:=origin}"
: "${GIT_WIP_PREFIX:=wip}"
: "${GIT_GACP_AUTO_ADD:=1}"
# ------------------------------------------------------------------------------
# Internal helper: ensure git is available and cwd is a git worktree
_git_require_repo()
{
if ! command -v git >/dev/null 2>&1; then
disp E "git command not found."
return 1
fi
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
disp E "Current directory is not inside a git repository."
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Internal helper: return default branch from remote HEAD, fallback to config
_git_default_branch()
{
local remote="${1:-$GIT_DEFAULT_REMOTE}"
local head
head=$(git symbolic-ref --quiet --short "refs/remotes/${remote}/HEAD" 2>/dev/null) || true
if [[ -n $head ]]; then
printf "%s\n" "${head#${remote}/}"
return 0
fi
printf "%s\n" "$GIT_MAIN_BRANCH"
return 0
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Display compact git status + branch tracking information
# Usage: gst [path]
gst()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'gst' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"gst --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "gst: Display short git status and branch tracking info.\n"
printf "Usage: gst [path]\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"gst --help\" to display usage."
return 1
;;
esac
done
local target="${1:-.}"
git -C "$target" status --short --branch
}
export -f gst
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Show a readable commit graph
# Usage: ggraph [-n limit]
ggraph()
{
local PARSED
PARSED=$(getopt -o hn: --long help,limit: -n 'ggraph' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"ggraph --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
local limit=30
while true; do
case "$1" in
-h|--help)
printf "ggraph: Display decorated git history graph.\n"
printf "Usage: ggraph [-n limit]\n"
printf "Options:\n"
printf "\t-n, --limit\tNumber of commits to display (default: 30)\n"
return 0
;;
-n|--limit)
limit="$2"
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"ggraph --help\" to display usage."
return 1
;;
esac
done
[[ $limit =~ ^[0-9]+$ ]] || {
disp E "Invalid limit: must be a positive integer."
return 1
}
_git_require_repo || return 1
git log --graph --decorate --oneline --all --max-count="$limit"
}
export -f ggraph
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Sync current branch with remote (fetch + rebase)
# Usage: gsync [remote]
gsync()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'gsync' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"gsync --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "gsync: Fetch and rebase current branch onto its remote tracking branch.\n"
printf "Usage: gsync [remote]\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"gsync --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
local remote="${1:-$GIT_DEFAULT_REMOTE}"
local branch upstream
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
disp I "Fetching from $remote..."
git fetch --prune "$remote" || return 1
if [[ -z $upstream ]]; then
disp W "No upstream configured for $branch, skipping rebase."
disp I "Set one with: git branch --set-upstream-to ${remote}/${branch} ${branch}"
return 0
fi
disp I "Rebasing $branch onto $upstream..."
git rebase "$upstream"
}
export -f gsync
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Add, commit, and push changes with automatic pull/rebase if needed
# Usage: gacp -m "message" [file1 file2 ...]
gacp()
{
local PARSED
PARSED=$(getopt -o ham: --long help,auto,message: -n 'gacp' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"gacp --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
local msg="" auto_add="$GIT_GACP_AUTO_ADD"
while true; do
case "$1" in
-h|--help)
printf "gacp: Run git add, git commit, and git push in one command.\n"
printf "Usage: gacp [-a] -m \"message\" [file1 file2 ...]\n"
printf "Options:\n"
printf "\t-a, --auto\tAutomatically add all modified files (git add -A)\n"
printf "\t-m, --message\tCommit message (mandatory)\n"
printf "\n"
printf "If files are provided, only those paths are added (-a is ignored).\n"
printf "If no file is provided and -a is active, all changes are added with git add -A.\n"
printf "Default for -a can be set via GIT_GACP_AUTO_ADD in profile.conf.\n"
printf "If the remote branch moved forward, gacp pulls with rebase before pushing.\n"
return 0
;;
-a|--auto)
auto_add=1
shift
;;
-m|--message)
msg="$2"
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"gacp --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
if [[ -z $msg ]]; then
disp E "Missing commit message. Use -m or --message."
return 1
fi
local branch upstream remote tracking_branch behind counts
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
if [[ $# -gt 0 ]]; then
auto_add=0
disp I "Adding selected paths..."
git add -- "$@" || return 1
elif [[ $auto_add -eq 1 ]]; then
disp I "Adding all changes..."
git add -A || return 1
else
disp E "No files specified. Use -a/--auto or provide file paths."
return 1
fi
if git diff --cached --quiet; then
disp W "No staged changes to commit."
return 1
fi
disp I "Creating commit..."
git commit -m "$msg" || return 1
if [[ -n $upstream ]]; then
remote="${upstream%%/*}"
tracking_branch="${upstream#*/}"
else
remote="$GIT_DEFAULT_REMOTE"
tracking_branch="$branch"
fi
disp I "Fetching from $remote..."
git fetch --prune "$remote" || return 1
if git rev-parse --verify --quiet "refs/remotes/${remote}/${tracking_branch}" >/dev/null; then
counts=$(git rev-list --left-right --count HEAD..."${remote}/${tracking_branch}" 2>/dev/null) || return 1
read -r _ behind <<< "$counts"
if [[ ${behind:-0} -gt 0 ]]; then
disp I "Remote branch is ahead, rebasing before push..."
git pull --rebase "$remote" "$tracking_branch" || return 1
fi
fi
if [[ -n $upstream ]]; then
disp I "Pushing to $upstream..."
git push || return 1
else
disp I "Pushing and setting upstream to ${remote}/${branch}..."
git push -u "$remote" "$branch" || return 1
fi
disp I "gacp complete."
return 0
}
export -f gacp
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Reset local branch to exact upstream state (stash local changes first)
# Usage: greset [target]
greset()
{
local PARSED
PARSED=$(getopt -o hx --long help,with-ignored -n 'greset' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"greset --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
local clean_ignored=0
while true; do
case "$1" in
-h|--help)
printf "greset: Reset current branch to upstream, stashing local changes first.\n"
printf "Usage: greset [target]\n"
printf "Options:\n"
printf "\t-x, --with-ignored\tAlso remove ignored files (git clean -fdx)\n"
printf "\n"
printf "Default target is current branch upstream (@{u}).\n"
printf "If no upstream exists, fallback target is <remote>/<branch>.\n"
printf "This command stashes local modifications (tracked + untracked),\n"
printf "drops local unpushed commits by hard-reset, and cleans untracked files.\n"
return 0
;;
-x|--with-ignored)
clean_ignored=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"greset --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
local branch upstream target remote old_head stash_msg stash_out stash_created=0 dropped=0
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
target="$1"
if [[ -z $target ]]; then
if [[ -n $upstream ]]; then
target="$upstream"
else
remote="$GIT_DEFAULT_REMOTE"
target="${remote}/${branch}"
fi
fi
if [[ -z $remote ]]; then
remote="${target%%/*}"
fi
old_head=$(git rev-parse HEAD 2>/dev/null) || return 1
if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then
stash_msg="greset:${branch}:$(date +'%Y-%m-%d %H:%M:%S')"
disp I "Stashing local changes as '$stash_msg'..."
stash_out=$(git stash push -u -m "$stash_msg" 2>&1) || {
disp E "Failed to stash local changes."
printf "%s\n" "$stash_out"
return 1
}
[[ $stash_out != "No local changes to save"* ]] && stash_created=1
fi
disp I "Fetching from $remote..."
git fetch --prune "$remote" || return 1
if ! git rev-parse --verify --quiet "$target" >/dev/null; then
disp E "Target '$target' does not exist."
return 1
fi
dropped=$(git rev-list --count "${target}..${old_head}" 2>/dev/null || printf "0")
disp W "Hard-resetting $branch to $target..."
git reset --hard "$target" || return 1
if (( clean_ignored )); then
git clean -fdx || return 1
else
git clean -fd || return 1
fi
if (( stash_created )); then
disp I "Local changes were stashed. Use 'git stash list' and 'git stash pop' when needed."
fi
disp I "greset complete. Dropped local-only commits: $dropped"
return 0
}
export -f greset
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Create a quick WIP commit for local checkpointing
# Usage: gwip [message]
gwip()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'gwip' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"gwip --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "gwip: Create a local checkpoint commit with all tracked/untracked changes.\n"
printf "Usage: gwip [message]\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"gwip --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
local msg
if [[ $# -gt 0 ]]; then
msg="$*"
else
msg="$GIT_WIP_PREFIX: $(date +'%Y-%m-%d %H:%M:%S')"
fi
git add -A || return 1
git commit -m "$msg"
}
export -f gwip
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Delete merged local branches (except protected branches)
# Usage: gprune [main-branch]
gprune()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'gprune' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"gprune --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "gprune: Delete local branches already merged into main branch.\n"
printf "Usage: gprune [main-branch]\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"gprune --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
local base="${1:-$(_git_default_branch "$GIT_DEFAULT_REMOTE")}" current deleted=0
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
disp I "Pruning branches merged into $base..."
while IFS= read -r b; do
[[ -z $b ]] && continue
[[ $b == "$current" ]] && continue
[[ $b == "$base" ]] && continue
[[ $b == "master" || $b == "main" || $b == "develop" || $b == "dev" ]] && continue
git branch -d "$b" >/dev/null 2>&1 && {
printf "Deleted: %s\n" "$b"
((deleted++))
}
done < <(git branch --merged "$base" | sed -E 's/^\*?\s*//')
(( deleted == 0 )) && disp I "No merged branches to delete."
}
export -f gprune
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Print repository root path
# Usage: groot
groot()
{
local PARSED
PARSED=$(getopt -o hg --long help,go -n 'groot' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"groot --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
local do_go=0
while true; do
case "$1" in
-h|--help)
printf "groot: Display the absolute path of the current repository root.\n"
printf "Usage: groot [-g|--go]\n"
printf "Options:\n"
printf "\t-g, --go\tChange current directory to repository root\n"
return 0
;;
-g|--go)
do_go=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"groot --help\" to display usage."
return 1
;;
esac
done
_git_require_repo || return 1
local root
root=$(git rev-parse --show-toplevel) || return 1
if (( do_go )); then
cd "$root" || {
disp E "Failed to move to repository root: $root"
return 1
}
return 0
fi
printf "%s\n" "$root"
}
export -f groot
# ------------------------------------------------------------------------------
load_conf git
# EOF

View File

@@ -36,48 +36,71 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Display list of commands and general informations # Display list of commands and general informations
# Usage: help # Usage: help [command]
help() help()
{ {
# If a command name is given, delegate to its --help output.
if [[ $# -gt 0 && "$1" != "--help" && "$1" != "-h" ]]; then
local cmd="$1"
if declare -F "$cmd" >/dev/null 2>&1 || command -v "$cmd" >/dev/null 2>&1; then
"$cmd" --help
else
disp E "Unknown command: $cmd"
return 1
fi
return
fi
# shellcheck disable=SC2154 # color code in disp.sh
# shellcheck disable=SC2059 # printf format is a color variable
printf "${BIWhite}Welcome to your profile! Here is a list of available commands:${DEFAULTCOL}\n\n" printf "${BIWhite}Welcome to your profile! Here is a list of available commands:${DEFAULTCOL}\n\n"
printf "busy\t\tMonitor /dev/urandom for a hex pattern — look busy\n"
printf "check_updates\tCheck for new versions of profile\n" printf "check_updates\tCheck for new versions of profile\n"
printf "clean\t\tErase backup files\n" printf "clean\t\tErase backup files in given directories, optionally recursive\n"
printf "disp\t\tDisplay formatted info/warning/error/debug messages\n" printf "disp\t\tDisplay formatted info/warning/error/debug messages\n"
printf "dwl\t\tDownload a URL to a local file\n" printf "dwl\t\tDownload a URL using curl, wget, or fetch transparently\n"
printf "expandlist\tExpand and quote item lists\n" printf "expandlist\tExpand glob expressions into a quoted, separated list\n"
printf "file_stats\tDisplay file size statistics for a path\n" printf "file_stats\tDisplay file size statistics for a path\n"
printf "findbig\t\tFind biggest files in the given (or current) directory\n" printf "findbig\t\tFind the biggest files in the given or current directory\n"
printf "finddead\tFind dead symbolic links in the given (or current) directory\n" printf "finddead\tFind dead symbolic links in the given or current directory\n"
printf "findzero\tFind empty files in the given (or current) directory\n" printf "findzero\tFind empty files in the given or current directory\n"
printf "genpwd\t\tGenerate secure passwords\n" printf "gacp\t\tAdd, commit and push changes (auto-pull if needed)\n"
printf "gpid\t\tGive the list of PIDs for the given process name\n" printf "genpwd\t\tGenerate one or more random secure passwords with configurable constraints\n"
printf "isipv4\t\tTell if the given IPv4 is valid\n" printf "ggraph\t\tDisplay decorated git history graph\n"
printf "isipv6\t\tTell if the given IPv6 is valid\n" printf "gprune\t\tDelete local branches already merged into main branch\n"
printf "ku\t\tKill process owned by users in parameter\n" printf "greset\t\tReset branch to upstream (stash local, drop local commits)\n"
printf "matrix\t\tDisplay matrix-style digital rain\n" printf "groot\t\tDisplay repository root path (or cd to it with -g)\n"
printf "mcd\t\tCreate a directory and go inside\n" printf "gsync\t\tFetch and rebase current branch onto upstream\n"
printf "meteo\t\tDisplay current weather forecast for the configured city\n" printf "gst\t\tDisplay short git status and branch tracking info\n"
printf "myextip\tDisplay current external/public IP\n" printf "gwip\t\tCreate a quick WIP checkpoint commit\n"
printf "pkgs\t\tSearch for the given package in installed ones\n" printf "gpid\t\tGive the list of PIDs matching the given process name(s)\n"
printf "ppg\t\tDisplay process matching the given parameter\n" printf "isipv4\t\tTell if the given parameter is a valid IPv4 address\n"
printf "ppn\t\tDisplay process matching the exact process name given in parameter\n" printf "isipv6\t\tTell if the given parameter is a valid IPv6 address\n"
printf "ppu\t\tDisplay processes owned by the given user\n" printf "ku\t\tKill all processes owned by the given user name or ID\n"
printf "profile_upgrade\tUpgrade profile to the latest version\n" printf "matrix\t\tConsole screensaver with Matrix-style digital rain (binary, kana, ascii charset)\n"
printf "pwdscore\tCalculate password strength score\n" printf "mcd\t\tCreate a directory and immediately move into it\n"
printf "rain\t\tLet the rain fall\n" printf "meteo\t\tDisplay weather forecast for the configured or given city\n"
printf "rmhost\t\tRemove host (IP and/or DNS name) from current known_hosts\n" printf "myextip\t\tGet information about your public IP address\n"
printf "rmspc\t\tRemove spaces from file and directory names\n" printf "pkgs\t\tSearch for a pattern in installed package names (dpkg/rpm, supports -i)\n"
printf "setlocale\tSet console language to the current locale\n" printf "ppg\t\tLook for the given pattern in running processes\n"
printf " * setc\tSet console language to C\n" printf "ppn\t\tList processes matching an exact command name\n"
printf " * setfr\tSet console language to French\n" printf "ppu\t\tList processes owned by a specific user\n"
printf " * setus\tSet console language to US English\n" printf "profile_upgrade\tUpgrade profile to the latest version (git pull or archive)\n"
printf "settrace\tActivate/deactivate call trace for script debugging\n" printf "pwdscore\tCalculate the strength score of a given password\n"
printf "showinfo\tShow welcome banner with basic system information\n" printf "rain\t\tConsole screensaver with falling-rain effect (multiple color themes)\n"
printf "ssr\t\tDo a root login to the given address\n" printf "rmhost\t\tRemove host (name and IP) from SSH known_hosts; supports --all-users as root\n"
printf "taz\t\tCompress smartly the given files or directory\n" printf "rmspc\t\tReplace spaces in filenames with underscores (or a custom character)\n"
printf "urlencode\tURL-encode the given text\n" printf "setlocale\tSet console locale to any installed locale\n"
printf "utaz\t\tUncompress archives in the given (or current) directory\n" printf " * setc\tSet locale to standard C (POSIX)\n"
printf "ver\t\tDisplay version of your copy of profile\n\n" printf " * set*\tLocale shortcuts generated from SET_LOCALE in profile.conf\n"
printf "settrace\tActivate or deactivate ERR trap to display backtrace on script errors\n"
printf "set_theme\tSwitch the prompt colour theme; no argument lists available themes\n"
printf "showinfo\tDisplay welcome banner and system information (figlet + neofetch/fastfetch)\n"
printf "ssr\t\tSSH into a server as root, forwarding extra ssh options\n"
printf "taz\t\tCompress files and directories into a chosen archive format\n"
printf "urlencode\tURL-encode a string\n"
printf "utaz\t\tSmartly uncompress archives (zip, tar.gz/bz2/xz/lz, rar, arj, lha, ace, 7z, zst, cpio, cab, deb, rpm)\n"
printf "ver\t\tDisplay the installed profile version\n\n"
printf "\nPlease use <command> --help to obtain usage details.\n" printf "\nPlease use <command> --help to obtain usage details.\n"
} }

View File

@@ -42,6 +42,7 @@ ver()
local PARSED local PARSED
PARSED=$(getopt -o h --long help -n 'ver' -- "$@") PARSED=$(getopt -o h --long help -n 'ver' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"ver --help\" to display usage." disp E "Invalid options, use \"ver --help\" to display usage."
return 1 return 1
@@ -82,6 +83,7 @@ meteo()
local PARSED local PARSED
PARSED=$(getopt -o h --long help -n 'meteo' -- "$@") PARSED=$(getopt -o h --long help -n 'meteo' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"meteo --help\" to display usage." disp E "Invalid options, use \"meteo --help\" to display usage."
return 1 return 1
@@ -133,6 +135,7 @@ showinfo()
local PARSED local PARSED
PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@") PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"showinfo --help\" to display usage." disp E "Invalid options, use \"showinfo --help\" to display usage."
return 1 return 1

View File

@@ -51,6 +51,7 @@ setlocale()
{ {
local PARSED local PARSED
PARSED=$(getopt -o h --long help -n 'setlocale' -- "$@") PARSED=$(getopt -o h --long help -n 'setlocale' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"setlocale --help\" to display usage." disp E "Invalid options, use \"setlocale --help\" to display usage."
return 1 return 1

View File

@@ -36,27 +36,52 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Download a resource using curl, wget, or fetch. # Download a resource using curl, wget, or fetch.
# Usage: dwl <url> [output_file] # Usage: dwl [-t <seconds>] <url> [output_file]
dwl() dwl()
{ {
case "$1" in local timeout=""
--help|-h)
echo "Usage: dwl <url> [output_file]" # Parse leading options before the URL.
echo "Downloads a resource using curl, wget, or fetch." while [[ $# -gt 0 ]]; do
echo "" case "$1" in
echo "Arguments:" --help|-h)
echo " url The full URL to download (http/https/ftp)." echo "Usage: dwl [-t <seconds>|--timeout <seconds>] <url> [output_file]"
echo " output_file (Optional) Path to save the file. If omitted, prints to stdout." echo "Downloads a resource using curl, wget, or fetch."
return 0 echo ""
;; echo "Arguments:"
echo " -t, --timeout Maximum time in seconds to wait for the transfer."
echo " url The full URL to download (http/https/ftp)."
echo " output_file (Optional) Path to save the file. If omitted, prints to stdout."
return 0
;;
-t|--timeout)
[[ -z "${2:-}" || ! "${2:-}" =~ ^[0-9]+$ ]] && {
echo "Error: --timeout requires a positive integer argument." >&2
return 1
}
timeout="$2"
shift 2
;;
--)
shift
break
;;
-*)
echo "Error: Unknown option '$1'. Try 'dwl --help'." >&2
return 1
;;
*)
break
;;
esac
done
case "${1:-}" in
"") "")
echo "Error: URL argument is missing." >&2 echo "Error: URL argument is missing." >&2
echo "Try 'get_resource --help' for usage." >&2 echo "Try 'dwl --help' for usage." >&2
return 1 return 1
;; ;;
esac
case "$1" in
http://*|https://*|ftp://*) ;; http://*|https://*|ftp://*) ;;
*) *)
echo "Error: '$1' does not look like a valid URL. Must start with http://, https://, or ftp://" >&2 echo "Error: '$1' does not look like a valid URL. Must start with http://, https://, or ftp://" >&2
@@ -65,14 +90,43 @@ dwl()
esac esac
local url="$1" local url="$1"
local output="$2" local output="${2:-}"
# Honour preferred tool from configuration; fall back to auto-detection. # Honour preferred tool from configuration; fall back to auto-detection.
local preferred="${DWL_PREFERRED_TOOL:-}" local preferred="${DWL_PREFERRED_TOOL:-}"
_try_curl() { [ -z "$output" ] && curl -sL "$url" || curl -sL -o "$output" "$url"; } _try_curl()
_try_wget() { [ -z "$output" ] && wget -qO- "$url" || wget -q -O "$output" "$url"; } {
_try_fetch() { [ -z "$output" ] && fetch -o - "$url" || fetch -o "$output" "$url"; } local args=(-sL)
[[ -n "$timeout" ]] && args+=(--max-time "$timeout" --connect-timeout "$timeout")
if [[ -z "$output" ]]; then
curl "${args[@]}" "$url"
else
curl "${args[@]}" -o "$output" "$url"
fi
}
_try_wget()
{
local args=(-q)
[[ -n "$timeout" ]] && args+=(--timeout="$timeout")
if [[ -z "$output" ]]; then
wget "${args[@]}" -O- "$url"
else
wget "${args[@]}" -O "$output" "$url"
fi
}
_try_fetch()
{
local args=()
[[ -n "$timeout" ]] && args+=(-T "$timeout")
if [[ -z "$output" ]]; then
fetch "${args[@]}" -o - "$url"
else
fetch "${args[@]}" -o "$output" "$url"
fi
}
if [[ -n "$preferred" ]]; then if [[ -n "$preferred" ]]; then
command -v "$preferred" >/dev/null 2>&1 || { command -v "$preferred" >/dev/null 2>&1 || {

View File

@@ -34,15 +34,98 @@
# * OF SUCH DAMAGE. # * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Detect the active package manager of the current distribution.
# Detection is based on /etc/os-release (ID / ID_LIKE), then falls back to
# checking available binaries in a fixed priority order.
# Echoes one of: apt dnf yum zypper pacman apk portage xbps nix
# Returns 1 if no known package manager could be identified.
get_pkgmgr()
{
local distro_id="" distro_like=""
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
distro_id=$( . /etc/os-release 2>/dev/null; printf '%s' "${ID:-}" )
# shellcheck disable=SC1091
distro_like=$( . /etc/os-release 2>/dev/null; printf '%s' "${ID_LIKE:-}" )
fi
# Map distro IDs/families to a package manager.
# ID_LIKE is space-separated and may list multiple families.
local id
for id in $distro_id $distro_like; do
case "${id,,}" in
debian|ubuntu|linuxmint|raspbian|pop|kali|elementary|zorin|neon|parrot)
echo "apt"
return 0
;;
fedora)
echo "dnf"
return 0
;;
rhel|centos|rocky|almalinux|ol|scientific|amzn)
command -v dnf >/dev/null 2>&1 && { echo "dnf"; return 0; }
echo "yum"
return 0
;;
opensuse*|sles|sled)
echo "zypper"
return 0
;;
arch|manjaro|endeavouros|garuda|artix|cachyos)
echo "pacman"
return 0
;;
alpine)
echo "apk"
return 0
;;
gentoo)
echo "portage"
return 0
;;
void)
echo "xbps"
return 0
;;
nixos)
echo "nix"
return 0
;;
esac
done
# Fallback: check for binaries in priority order.
local bin
for bin in apt apt-get dnf yum zypper pacman apk emerge xbps-install nix-env; do
command -v "$bin" >/dev/null 2>&1 && {
case "$bin" in
apt-get) echo "apt" ;;
emerge) echo "portage" ;;
xbps-install) echo "xbps" ;;
nix-env) echo "nix" ;;
*) echo "$bin" ;;
esac
return 0
}
done
return 1
}
export -f get_pkgmgr
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Look for a package within installed one # Look for a package within installed one
# Usage: dpkgs <string> # Usage: pkgs <string>
pkgs() pkgs()
{ {
local ignore_case=${PKGS_DEFAULT_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' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"pkgs --help\" to display usage." disp E "Invalid options, use \"pkgs --help\" to display usage."
return 1 return 1
@@ -84,13 +167,28 @@ pkgs()
local grep_opt="" local grep_opt=""
(( ignore_case )) && grep_opt="-i" (( ignore_case )) && grep_opt="-i"
command -v dpkg >/dev/null 2>&1 && local cmd="dpkg -l" local pkgmgr
command -v rpm >/dev/null 2>&1 && local cmd="rpm -qa" pkgmgr=$(get_pkgmgr) || {
if [[ -z $cmd ]]; then disp E "No usable package manager could be detected on this system."
disp E "No usable package manager seems unavialable."
return 2 return 2
fi }
$cmd | grep $grep_opt $pkg
local -a list_cmd
case "$pkgmgr" in
apt) list_cmd=(dpkg-query -l) ;;
dnf|yum|zypper) list_cmd=(rpm -qa) ;;
pacman) list_cmd=(pacman -Q) ;;
apk) list_cmd=(apk list --installed) ;;
portage) list_cmd=(qlist -I) ;;
xbps) list_cmd=(xbps-query -l) ;;
nix) list_cmd=(nix-env -q) ;;
*)
disp E "Package manager '$pkgmgr' is not supported by pkgs."
return 2
;;
esac
"${list_cmd[@]}" | grep ${grep_opt:+"$grep_opt"} "$pkg"
} }
export -f pkgs export -f pkgs
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@@ -121,6 +121,7 @@ ppn()
# -e: select all processes # -e: select all processes
# -o: specify custom output columns (PID and Command name) # -o: specify custom output columns (PID and Command name)
# grep -w: ensures exact word matching so 'bash' doesn't match 'dbash' # grep -w: ensures exact word matching so 'bash' doesn't match 'dbash'
# shellcheck disable=SC2009 # pgrep do not offer the -w switch
ps -eo pid,comm | grep -w "$1" ps -eo pid,comm | grep -w "$1"
} }
export -f ppn export -f ppn
@@ -200,8 +201,7 @@ ku()
disp E "Usage: ku <username1 [username2 ...]>" disp E "Usage: ku <username1 [username2 ...]>"
return 1 return 1
fi fi
local users="$@" for u in "$@"; do
for u in $users; do
if ! id "$u" >/dev/null 2>&1; then if ! id "$u" >/dev/null 2>&1; then
disp E "User '$u' does not exist." disp E "User '$u' does not exist."
return 1 return 1
@@ -227,7 +227,7 @@ kt()
return 0 return 0
fi fi
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
disp E "Usage: ppg <string>" disp E "Usage: kt <pid>"
return 1 return 1
fi fi
@@ -238,7 +238,8 @@ kt()
return 1 return 1
fi fi
local children_pids=$(pgrep -P "$parent_pid") local children_pids
children_pids=$(pgrep -P "$parent_pid")
for pid in $children_pids; do for pid in $children_pids; do
kt "$pid" "$@" || break kt "$pid" "$@" || break

View File

@@ -140,9 +140,14 @@ load_theme()
continue continue
fi fi
# Strip surrounding quotes # Strip surrounding quotes (handles inline trailing comments like KEY="val" # note)
_lth_value="${_lth_value#\"}" ; _lth_value="${_lth_value%\"}" if [[ "$_lth_value" == '"'* ]]; then
_lth_value="${_lth_value#\'}" ; _lth_value="${_lth_value%\'}" _lth_value="${_lth_value#\"}"
_lth_value="${_lth_value%%\"*}"
elif [[ "$_lth_value" == "'"* ]]; then
_lth_value="${_lth_value#\'}"
_lth_value="${_lth_value%%\'*}"
fi
if [[ "$_lth_value" =~ $_lth_ref_re ]]; then if [[ "$_lth_value" =~ $_lth_ref_re ]]; then
# Safe colour variable reference — resolve via indirection # Safe colour variable reference — resolve via indirection
@@ -159,6 +164,67 @@ load_theme()
fi fi
done < "$theme_file" done < "$theme_file"
} }
# Not exported, it remains private
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Dynamically switch the prompt theme for the current shell session.
# Calls load_theme to apply the new colour values immediately, then updates
# PROMPT_THEME so subshells and the set_prompt fallback chain reflect the
# change. PROMPT_THEME_DIR is honoured when set.
# Usage: set_theme [theme_name_or_path]
# With no argument (or -l / --list), lists available .theme files.
set_theme()
{
local theme_dir="${PROMPT_THEME_DIR:-${MYPATH}/profile.d/themes}"
# -- help mode -----------------------------------------------------------
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "set_theme: Switch the prompt colour theme for the current shell session.\n\n"
printf "Usage: set_theme [options] [theme]\n\n"
printf "Options:\n"
printf " -h, --help Display this help screen\n"
printf " -l, --list List available themes (default when no argument is given)\n\n"
printf "Arguments:\n"
printf " theme Bare theme name (e.g. 'dark') or an explicit path to a .theme file.\n"
printf " Themes are searched in: %s\n" "$theme_dir"
printf " Override with PROMPT_THEME_DIR in profile.conf [prompt].\n\n"
printf "Examples:\n"
printf " set_theme — list available themes\n"
printf " set_theme dark — apply the dark theme\n"
printf " set_theme ~/my.theme — apply a theme by path\n"
return 0
fi
# -- list mode -----------------------------------------------------------
if [[ $# -eq 0 || "$1" == "-l" || "$1" == "--list" ]]; then
printf "Available themes in %s:\n" "$theme_dir"
local f name
for f in "$theme_dir"/*.theme; do
[[ -f "$f" ]] || continue
name="${f##*/}"
name="${name%.theme}"
if [[ "$name" == "${PROMPT_THEME:-}" ]]; then
printf " * %s (active)\n" "$name"
else
printf " %s\n" "$name"
fi
done
return 0
fi
# -- apply mode ----------------------------------------------------------
local theme_name="$1"
# Reset colours to defaults before loading the new theme
set_colors
load_theme "$theme_name" || return 1
export PROMPT_THEME="$theme_name"
disp I "Prompt theme set to $theme_name."
}
export -f set_theme
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -186,7 +252,7 @@ function timer_start
# into a human-readable string with appropriate units (us, ms, s, m, h # into a human-readable string with appropriate units (us, ms, s, m, h
function timer_stop function timer_stop
{ {
local delta_us=$((($(timer_now) - $timer_start) / 1000)) local delta_us=$((($(timer_now) - timer_start) / 1000))
local us=$((delta_us % 1000)) local us=$((delta_us % 1000))
local ms=$(((delta_us / 1000) % 1000)) local ms=$(((delta_us / 1000) % 1000))
local s=$(((delta_us / 1000000) % 60)) local s=$(((delta_us / 1000000) % 60))
@@ -225,43 +291,48 @@ set_prompt()
# Resolve theme/config colours with hardcoded fallbacks # Resolve theme/config colours with hardcoded fallbacks
local _time_fg="${PROMPT_COLOR_TIME_FG:-$Blue}" local _time_fg="${PROMPT_COLOR_TIME_FG:-$Blue}"
local _time_bg="${PROMPT_COLOR_TIME_BG:-$On_IBlack}" local _time_bg="${PROMPT_COLOR_TIME_BG:-$On_White}"
local _bar_bg="${PROMPT_COLOR_BAR_BG:-$On_Blue}" local _bar_bg="${PROMPT_COLOR_BAR_BG:-$On_Blue}"
local _ok_fg="${PROMPT_COLOR_OK_FG:-$White}" local _ok_fg="${PROMPT_COLOR_OK_FG:-$BWhite}"
local _ok_mark="${PROMPT_COLOR_OK_MARK:-$Green}" local _ok_mark="${PROMPT_COLOR_OK_MARK:-$BGreen}"
local _err_bg="${PROMPT_COLOR_ERR_BG:-$On_Red}" local _err_bg="${PROMPT_COLOR_ERR_BG:-$On_Red}"
local _err_fg="${PROMPT_COLOR_ERR_FG:-$White}" local _err_fg="${PROMPT_COLOR_ERR_FG:-$White}"
local _err_mark="${PROMPT_COLOR_ERR_MARK:-$BYellow}" local _err_mark="${PROMPT_COLOR_ERR_MARK:-$BYellow}"
local _root_fg="${PROMPT_COLOR_ROOT_FG:-$Red}" local _root_fg="${PROMPT_COLOR_ROOT_FG:-$Red}"
local _user_fg="${PROMPT_COLOR_USER_FG:-$Green}" local _user_fg="${PROMPT_COLOR_USER_FG:-$BGreen}"
local _dir_fg="${PROMPT_COLOR_DIR_FG:-$ICyan}" local _dir_fg="${PROMPT_COLOR_DIR_FG:-$ICyan}"
# Begin with time # Begin with time (cursor-save is non-printing; all ANSI sequences wrapped
PS1="\[\e[s${_time_fg}${_time_bg} [ \t ] ${_bar_bg}" # in \[...\] so bash does not count them toward the visible line width).
# Every fg colour is combined with its section bg in the same \[...\] block
# so that even "reset" colours (0;Xm) cannot strip the background.
PS1="\[\e[s\]\[${_time_fg}${_time_bg}\] [ \t ] \[${_bar_bg}\]"
# Add exit status of 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+="${_ok_fg}${_bar_bg} [ \$Last_Command " PS1+="\[${_ok_fg}${_bar_bg}\] [ $Last_Command "
PS1+="${_ok_mark}${Checkmark} " PS1+="\[${_ok_mark}${_bar_bg}\]${Checkmark} "
# Add the elapsed time, then close the status section and return to bar bg.
timer_stop
PS1+="($timer_show)\[${_ok_fg}${_bar_bg}\] ] "
else else
PS1+="${_err_fg}${_err_bg} [ \$Last_Command " PS1+="\[${_err_fg}${_err_bg}\] [ $Last_Command "
PS1+="${_err_mark}${FancyX} " PS1+="\[${_err_mark}${_err_bg}\]${FancyX} "
timer_stop
PS1+="($timer_show)\[${_err_fg}${_err_bg}\] ] "
fi fi
# Add the elapsed time
timer_stop
PS1+="($timer_show)${_ok_fg} ] ${_bar_bg} "
# If root, print the host in root colour. Otherwise use user colour. # If root, print the host in root colour. Otherwise use user colour.
if [[ $EUID -eq 0 ]]; then if [[ $EUID -eq 0 ]]; then
PS1+="${_root_fg}\\u${_user_fg}@\\h" PS1+="\[${_root_fg}${_bar_bg}\] \\u\[${_user_fg}${_bar_bg}\]@\\h"
else else
PS1+="${_user_fg}\\u@\\h" PS1+="\[${_user_fg}${_bar_bg}\] \\u@\\h"
fi fi
PS1+="\e[K\e[u$DEFAULTCOL\n" PS1+="\[\e[K\e[u\]\[$RESETCOL\]\n"
# Print the working directory and prompt marker, then reset colour. # Print the working directory and prompt marker, then reset colour.
PS1+="${_dir_fg}\\w \\\$$DEFAULTCOL " PS1+="\[${_dir_fg}\]\\w \\\$\[$RESETCOL\] "
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@@ -65,6 +65,7 @@ genpwd()
PARSED=$(getopt -o hsnule:L:o: --long \ PARSED=$(getopt -o hsnule:L:o: --long \
help,nosymbols,nonumbers,noup,nolow,extracars:,length:,occurences:,occurrences: \ help,nosymbols,nonumbers,noup,nolow,extracars:,length:,occurences:,occurrences: \
-n 'genpwd' -- "$@") -n 'genpwd' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then return 1; fi if [[ $? -ne 0 ]]; then return 1; fi
eval set -- "$PARSED" eval set -- "$PARSED"

View File

@@ -44,6 +44,7 @@ rmhost()
local -a known_hosts_files=() local -a known_hosts_files=()
PARSED=$(getopt -o ha --long help,all-users -n 'rmhost' -- "$@") PARSED=$(getopt -o ha --long help,all-users -n 'rmhost' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then return 1; fi if [[ $? -ne 0 ]]; then return 1; fi
eval set -- "$PARSED" eval set -- "$PARSED"
@@ -194,6 +195,7 @@ ssr()
ssh_default_opts=(-Y) ssh_default_opts=(-Y)
fi fi
# shellcheck disable=SC2029
ssh "${ssh_default_opts[@]}" root@"$srv" "$@" ssh "${ssh_default_opts[@]}" root@"$srv" "$@"
} }
export -f ssr export -f ssr

84
profile.d/themes/abyss.theme Executable file → Normal file
View File

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

84
profile.d/themes/adwaita.theme Executable file → Normal file
View File

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

64
profile.d/themes/dark.theme Executable file → Normal file
View File

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

64
profile.d/themes/default.theme Executable file → Normal file
View File

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

70
profile.d/themes/light.theme Executable file → Normal file
View File

@@ -1,35 +1,35 @@
# Light prompt theme — white bar, blue user, purple path # Light prompt theme — white bar, blue user, purple path
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Theme files are NOT executed as shell scripts. load_theme() parses them # Theme files are NOT executed as shell scripts. load_theme() parses them
# line by line. Only the following value forms are accepted: # line by line. Only the following value forms are accepted:
# #
# KEY="$ColorVarName" — reference to a colour variable from disp.sh # KEY="$ColorVarName" — reference to a colour variable from disp.sh
# KEY="${ColorVarName}" — same with braces # KEY="${ColorVarName}" — same with braces
# KEY="\e[...m" — raw ANSI escape sequence (single block) # KEY="\e[...m" — raw ANSI escape sequence (single block)
# #
# Accepted keys: # Accepted keys:
# PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt]) # PROMPT_COLOR_* — prompt slot colours (see profile.conf [prompt])
# Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette # Standard colour vars — Black, Blue, On_IBlack, … (overrides the palette
# from disp.sh for the whole shell session) # from disp.sh for the whole shell session)
# #
# Any unknown key, unsafe value, or shell construct will be ignored with a # Any unknown key, unsafe value, or shell construct will be ignored with a
# warning — theme files cannot execute code. # warning — theme files cannot execute code.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Opposite of dark.theme: backgrounds flip to bright whites, foregrounds # Opposite of dark.theme: backgrounds flip to bright whites, foregrounds
# shift to their dark/regular equivalents for contrast on a light terminal. # 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_FG="$BBlack" # Clock text (bold black — forces true black on terminals that render Black as dark grey)
PROMPT_COLOR_TIME_BG="$On_IWhite" # Clock background (On_Black → On_IWhite) 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_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_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_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_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_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_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_ROOT_FG="$Red" # Username when root (BIRed → Red)
PROMPT_COLOR_USER_FG="$Blue" # Username@host normal user (ICyan → Blue) PROMPT_COLOR_USER_FG="$Blue" # Username@host normal user (ICyan → Blue)
PROMPT_COLOR_DIR_FG="$Purple" # Working directory (IPurple → Purple) PROMPT_COLOR_DIR_FG="$Purple" # Working directory (IPurple → Purple)

128
profile.d/themes/monochrome.theme Executable file → Normal file
View File

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

90
profile.d/themes/monokai.theme Executable file → Normal file
View File

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

84
profile.d/themes/plasma.theme Executable file → Normal file
View File

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

254
profile.d/themes/solarized-light.theme Executable file → Normal file
View File

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

244
profile.d/themes/solarized.theme Executable file → Normal file
View File

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

View File

@@ -54,6 +54,7 @@ check_updates()
local vfile="" lastver="" local vfile="" lastver=""
PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@") PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"check_updates --help\" to display usage." disp E "Invalid options, use \"check_updates --help\" to display usage."
return 2 return 2
@@ -89,9 +90,14 @@ check_updates()
return 4 return 4
} }
dwl "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || { # In quiet mode (startup), use a short timeout so a missing or slow network
# never blocks the interactive prompt.
local dwl_opts=()
(( quiet == 1 )) && dwl_opts+=(-t 3)
dwl "${dwl_opts[@]}" "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || {
rm -f "$vfile" rm -f "$vfile"
disp E "Cannot download version file; unable to continue." (( quiet != 1 )) && disp E "Cannot download version file; unable to continue."
return 5 return 5
} }
@@ -128,6 +134,7 @@ profile_upgrade()
local tmpdir="" archive="" extracted_root="" local tmpdir="" archive="" extracted_root=""
PARSED=$(getopt -o hf:t:nFb:g --long help,file:,tmpdir:,dry-run,force,branch:,switch-to-git -n 'profile_upgrade' -- "$@") PARSED=$(getopt -o hf:t:nFb:g --long help,file:,tmpdir:,dry-run,force,branch:,switch-to-git -n 'profile_upgrade' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"profile_upgrade --help\" to display usage." disp E "Invalid options, use \"profile_upgrade --help\" to display usage."
return 2 return 2
@@ -215,8 +222,8 @@ profile_upgrade()
} }
if (( dry_run )); then if (( dry_run )); then
disp I "[dry-run] rm -rf \"$MYPATH\"/.git" disp I "[dry-run] rm -rf \"$MYPATH\"/.git"
disp I "[dry-run] git clone "$BASE_URL" \"$MYPATH\"" disp I "[dry-run] git clone $BASE_URL \"$MYPATH\""
[[ -n "$branch" ]] && disp I "[dry-run] git -C \"$MYPATH\" checkout "$branch"" [[ -n "$branch" ]] && disp I "[dry-run] git -C \"$MYPATH\" checkout $branch"
return 0 return 0
fi fi

View File

@@ -35,19 +35,134 @@
# * OF SUCH DAMAGE. # * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
_profile_is_sourced()
{
[[ "${BASH_SOURCE[0]}" != "$0" ]]
}
_profile_finish()
{
local rc="${1:-0}"
if _profile_is_sourced; then
return "$rc"
fi
exit "$rc"
}
_profile_install_in_file()
{
local rc_file="$1"
local source_line="$2"
[[ -f "$rc_file" ]] || touch "$rc_file" || {
printf "[ Error ] Cannot create %s\n" "$rc_file" >&2
return 1
}
if grep -Fqx "$source_line" "$rc_file"; then
printf "[ Info ] Already configured in %s\n" "$rc_file"
return 0
fi
printf "\n%s\n" "$source_line" >> "$rc_file" || {
printf "[ Error ] Cannot write to %s\n" "$rc_file" >&2
return 1
}
printf "[ Info ] Added profile source line to %s\n" "$rc_file"
return 0
}
_profile_install()
{
local install_bashrc=0
local install_profile=0
local target_selected=0
local script_dir source_line rc=0
while [[ $# -gt 0 ]]; do
case "$1" in
--bashrc)
install_bashrc=1
target_selected=1
;;
--profile)
install_profile=1
target_selected=1
;;
-h|--help)
printf "Usage: %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}"
printf "If no target is specified, both ~/.bashrc and ~/.profile are configured.\n"
return 0
;;
*)
printf "[ Error ] Unknown install option: %s\n" "$1" >&2
return 2
;;
esac
shift
done
if (( target_selected == 0 )); then
install_bashrc=1
install_profile=1
fi
script_dir=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")")
source_line="source \"$script_dir/profile.sh\""
if (( install_bashrc == 1 )); then
_profile_install_in_file "$HOME/.bashrc" "$source_line" || rc=$?
fi
if (( install_profile == 1 )); then
_profile_install_in_file "$HOME/.profile" "$source_line" || rc=$?
fi
return "$rc"
}
if [[ $# -gt 0 ]]; then
case "$1" in
--install)
shift
_profile_install "$@"
_profile_finish $?
;;
-h|--help)
printf "Usage: source %s\n" "${BASH_SOURCE[0]}"
printf " %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}"
_profile_finish 0
;;
*)
printf "[ Error ] Unknown option: %s\n" "$1" >&2
_profile_finish 2
;;
esac
fi
if ! _profile_is_sourced; then
printf "[ Warning ] profile.sh is designed to be sourced, not executed directly.\n" >&2
printf "Use: source \"%s\"\n" "$(realpath -s "${BASH_SOURCE[0]}")" >&2
printf "Or run: %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}" >&2
exit 1
fi
if [[ ! $SHELL =~ bash ]]; then if [[ ! $SHELL =~ bash ]]; then
echo "That environment script is designed to be used with bash being the shell." echo "That environment script is designed to be used with bash being the shell."
echo "Please consider using bash to enjoy our features!" echo "Please consider using bash to enjoy our features!"
return 1 _profile_finish 1
fi fi
# Required for associative arrays (4.0+) and namerefs (4.3+) # Required for associative arrays (4.0+) and namerefs (4.3+)
if ((BASH_VERSINFO[0] < 4)) || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then if ((BASH_VERSINFO[0] < 4)) || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then
echo "[ Error ] This profile requires Bash 4.3 or higher." echo "[ Error ] This profile requires Bash 4.3 or higher."
echo "Current version: $BASH_VERSION" echo "Current version: $BASH_VERSION"
return 1 2>/dev/null || exit 1 (return 0 2>/dev/null) && return 1 || exit 1
fi fi
unset -f _profile_is_sourced _profile_finish _profile_install_in_file _profile_install
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# path* : private functions for PATH variable management # path* : private functions for PATH variable management
pathremove() pathremove()
@@ -66,17 +181,17 @@ pathremove()
export "$pathvar=$newpath" export "$pathvar=$newpath"
} }
pathprepend() #pathprepend() # Unused for now, but might be useful in the future
{ #{
[[ -z "$1" ]] && return 0 # [[ -z "$1" ]] && return 0
local pathvar="${2:-PATH}" # local pathvar="${2:-PATH}"
[[ "$pathvar" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] || { # [[ "$pathvar" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] || {
printf "pathprepend: unsafe variable name '%s'\n" "$pathvar" >&2 # printf "pathprepend: unsafe variable name '%s'\n" "$pathvar" >&2
return 1 # return 1
} # }
pathremove "$1" "$pathvar" # pathremove "$1" "$pathvar"
export "$pathvar=$1${!pathvar:+:${!pathvar}}" # export "$pathvar=$1${!pathvar:+:${!pathvar}}"
} #}
pathappend() pathappend()
{ {
@@ -98,7 +213,7 @@ parse_conf()
{ {
local config_file="$1" local config_file="$1"
local current_section="" local current_section=""
local line key value local key value
[[ ! -f "$config_file" ]] && return 1 [[ ! -f "$config_file" ]] && return 1
@@ -140,6 +255,7 @@ parse_conf()
# Use a nameref for safe, eval-free assignment # Use a nameref for safe, eval-free assignment
local -n current_array="CONF_$current_section" local -n current_array="CONF_$current_section"
# shellcheck disable=SC2034 # Dynamic var creation
current_array["$key"]="$value" current_array["$key"]="$value"
fi fi
done < "$config_file" done < "$config_file"
@@ -168,6 +284,7 @@ load_alias()
# Only alias if the base command is executable # Only alias if the base command is executable
if command -v "$base_cmd" >/dev/null 2>&1; then if command -v "$base_cmd" >/dev/null 2>&1; then
# shellcheck disable=SC2139 # Dynamic alias creation
alias "$key"="$cmd" alias "$key"="$cmd"
fi fi
done done
@@ -181,7 +298,8 @@ load_conf()
{ {
local section_name="CONF_$1" local section_name="CONF_$1"
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 1 # Missing section is not an error: modules can rely on built-in defaults.
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 0
local -n current_vars="$section_name" local -n current_vars="$section_name"
@@ -204,22 +322,24 @@ load_conf()
# Because we're more likely to be sourced, we use BASH_SOURCE to get the path # Because we're more likely to be sourced, we use BASH_SOURCE to get the path
# of the sourced file instead of $0 # of the sourced file instead of $0
if [[ -z "$PROFILE_PATH" ]]; then if [[ -z "$PROFILE_PATH" ]]; then
export MYPATH=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")") MYPATH=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")")
else else
export MYPATH="$PROFILE_PATH" MYPATH="$PROFILE_PATH"
fi fi
export MYPATH
if [[ ! -e "$MYPATH/profile.sh" ]]; then if [[ ! -e "$MYPATH/profile.sh" ]]; then
echo "[ Warning ] Path detection failed, trying to use pwd..." echo "[ Warning ] Path detection failed, trying to use pwd..."
MYPATH=$(pwd) MYPATH=$(pwd)
if [[ ! -e "$MYPATH/profile.sh" ]]; then if [[ ! -e "$MYPATH/profile.sh" ]]; then
echo "[ Error ] Impossible to determine installation path, pretty much nothing will work." echo "[ Error ] Unable to determine installation path, pretty much nothing will work."
fi fi
fi fi
if [[ ! -s "$MYPATH/version" ]]; then if [[ ! -s "$MYPATH/version" ]]; then
echo "[ Warning ] Impossible to determine running version of profile, your installation might be broken." echo "[ Warning ] Unable to determine running profile version; your installation might be broken."
fi fi
export PROFVERSION=$(cat "$MYPATH"/version) PROFVERSION=$(cat "$MYPATH"/version)
export PROFVERSION
# Build PATH environment variable # Build PATH environment variable
if [[ $EUID -eq 0 ]]; then if [[ $EUID -eq 0 ]]; then
@@ -231,6 +351,10 @@ fi
# Parse and load general configuration # Parse and load general configuration
export PROFILE_CONF="$MYPATH/profile.conf" export PROFILE_CONF="$MYPATH/profile.conf"
parse_conf "$PROFILE_CONF" parse_conf "$PROFILE_CONF"
# Overload with user configuration if it exists
if [[ -f "$HOME/.profile.conf" ]]; then
parse_conf "$HOME/.profile.conf"
fi
load_conf system # Load Bash system behavior configuration (history, pager, etc.) load_conf system # Load Bash system behavior configuration (history, pager, etc.)
load_conf general # General purpose configuration (compilation flags, etc.) load_conf general # General purpose configuration (compilation flags, etc.)
@@ -250,6 +374,14 @@ shopt -u nullglob
[[ $- == *i* ]] && export INTERACTIVE=1 [[ $- == *i* ]] && export INTERACTIVE=1
if [[ $INTERACTIVE ]]; then if [[ $INTERACTIVE ]]; then
# Load custom bash completions
shopt -s nullglob
for _compl in "$MYPATH/profile.d/bash-completion/"*.sh; do
[[ -f "$_compl" && -r "$_compl" ]] && . "$_compl"
done
unset _compl
shopt -u nullglob
# For compiling (as we often compile with LFS/0linux...) # For compiling (as we often compile with LFS/0linux...)
#Aliases #Aliases
load_alias aliases load_alias aliases
@@ -258,11 +390,21 @@ if [[ $INTERACTIVE ]]; then
trap 'timer_start' DEBUG trap 'timer_start' DEBUG
PROMPT_COMMAND='set_prompt' PROMPT_COMMAND='set_prompt'
# Set default language # Set default language from DEFAULT_LANG config key (set in [general]).
setfr # The value must match one of the alias names defined in SET_LOCALE so that
# the corresponding set<alias> function exists after build_locale_shortcuts.
if [[ -n "${DEFAULT_LANG:-}" ]]; then
_lang_fn="set${DEFAULT_LANG}"
if declare -F "$_lang_fn" >/dev/null 2>&1; then
"$_lang_fn"
else
disp W "DEFAULT_LANG '$DEFAULT_LANG' has no matching locale shortcut (check SET_LOCALE in profile.conf)."
fi
unset _lang_fn
fi
showinfo && printf "\n" showinfo && printf "\n"
check_updates -q check_updates -q
disp I "Profile version $PROFVERSION chargé..." disp I "Profile version $PROFVERSION loaded..."
fi fi
# Cleanup # Cleanup

View File

@@ -1 +1 @@
3.99.1-4_rc_1 4.1.0