26 Commits

Author SHA1 Message Date
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
34 changed files with 542 additions and 195 deletions

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

@@ -68,7 +68,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 |
@@ -204,7 +205,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 +215,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

@@ -7,6 +7,32 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
--- ---
## [3.99.2-4_rc_2] — 2026-04-21
### Fixed
- **`prompt.sh`** — `\$Last_Command` in PS1 was escaped, preventing the exit
code from ever appearing in the prompt (the local variable no longer exists
when PS1 is rendered by bash). Removed the backslash so the value is embedded
at `set_prompt` build time.
- **`filefct.sh``file_stats()`** — a stray unconditional `shift` after
`esac` doubled-shifted arguments already shifted by each `case` branch;
successive options such as `-H -d` were silently skipped.
- **`packages.sh``pkgs()`** — replaced the unreliable binary-presence test
(`command -v dpkg / rpm`) with the new `get_pkgmgr` function. Also corrected
a typo in the "no package manager" error message (`avialable``available`).
- **`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 ## [3.99.1-4_rc_1] — 2026
### Added ### Added

View File

@@ -29,9 +29,48 @@ to target). Stale forks cause avoidable merge conflicts.
--- ---
## 3. Development environment ## 3. Branch policy
| Requirement | Minimum version | Notes | | Branch | Purpose |
|---|---|
| `master` | Main development branch — new features and enhancements go here |
| `<version>` (e.g. `3.x`) | Maintenance branch for a released version — bugfixes backported from `master` |
**New functionality** must always target `master`.
**Bugfixes** must target the branch where the bug was introduced:
- If the bug exists in a released version, open the fix against that version's
maintenance branch first, then cherry-pick onto `master`.
- 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
merged back into `master` before the final release.
Do **not** add new features to a maintenance branch.
---
## 4. Versioning scheme
Versions follow the format **`MAJOR.MINOR.PATCH`** where the `MINOR` number
conveys the development stage of the next major release:
| Minor range | Stage | Rules |
|---|---|---|
| `x.90.y` | **Alpha** toward `x+1` | Stays on `master`. Development is open: new features are welcome, regressions are acceptable. |
| `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. |
| `x.99.y` | **RC** toward `x+1` | Bugfixes only. No new features. No regression allowed. Becomes `x+1.0.0` when stable. |
Examples: `3.90.1` is the first alpha toward `4.0`, `3.99.2` is the second
release candidate for `4.0`.
The `PATCH` number increments freely within a stage. A bump in `MINOR`
(e.g. `90``95`) always indicates a stage promotion in development phase.
Any experimental version must have it's dedicated branch.
---
## 5. Development environment
|---|---|---| |---|---|---|
| Bash | 4.3 | Namerefs (`local -n`) required | | Bash | 4.3 | Namerefs (`local -n`) required |
| shellcheck | any recent | Run before every commit | | shellcheck | any recent | Run before every commit |
@@ -52,7 +91,7 @@ brew install shellcheck
--- ---
## 4. Code style ## 6. Code style
### General rules ### General rules
- **Bash only** — no external interpreters in core modules. Python or Perl is - **Bash only** — no external interpreters in core modules. Python or Perl is
@@ -62,8 +101,8 @@ brew install shellcheck
- **`[[ … ]]`** for all conditionals — not `[ … ]`. - **`[[ … ]]`** for all conditionals — not `[ … ]`.
- **`(( … ))`** for arithmetic — not `$(( … ))` in conditionals. - **`(( … ))`** for arithmetic — not `$(( … ))` in conditionals.
- **`local`** for all function-internal variables — avoid polluting the - **`local`** for all function-internal variables — avoid polluting the
environment. environment. Prefer upper case for global and lowercase for local.
- **`printf`** instead of `echo` wherever the format matters. - **`printf`** instead of `echo` all the time.
- **Never `eval`** — use namerefs (`local -n`), `${!varname}` indirection, or - **Never `eval`** — use namerefs (`local -n`), `${!varname}` indirection, or
`declare -g` instead. `declare -g` instead.
- **No hardcoded defaults** — wire every configurable value through - **No hardcoded defaults** — wire every configurable value through
@@ -100,7 +139,7 @@ Add the `load_conf` call near the top after any variable declarations.
--- ---
## 5. Configuration keys ## 7. Configuration keys
When adding a configurable default: When adding a configurable default:
@@ -110,7 +149,7 @@ When adding a configurable default:
--- ---
## 6. Theming ## 8. Theming
New theme files go in `profile.d/themes/` with a `.theme` extension. New theme files go in `profile.d/themes/` with a `.theme` extension.
They are **parsed, not executed** — do not add shell logic. They are **parsed, not executed** — do not add shell logic.
@@ -118,7 +157,7 @@ See the existing themes and `README.md §4.4` for the allowed syntax.
--- ---
## 7. Running shellcheck ## 9. Running shellcheck
```bash ```bash
shellcheck -x profile.sh profile.d/*.sh shellcheck -x profile.sh profile.d/*.sh
@@ -130,7 +169,7 @@ comment explaining why the suppression is necessary.
--- ---
## 8. Submitting a contribution ## 10. Submitting a contribution
### Via Git (preferred) ### Via Git (preferred)
1. Contact the maintainer to obtain push access, or fork on the Gitea instance. 1. Contact the maintainer to obtain push access, or fork on the Gitea instance.
@@ -156,7 +195,7 @@ Reference issue numbers if applicable: closes #42.
--- ---
## 9. What will be rejected ## 11. What will be rejected
- Code requiring packages not in a minimal Debian or CentOS install. - Code requiring packages not in a minimal Debian or CentOS install.
- Use of `eval`, `source`-based config loading, or other code-injection vectors. - Use of `eval`, `source`-based config loading, or other code-injection vectors.
@@ -166,6 +205,6 @@ Reference issue numbers if applicable: closes #42.
--- ---
## 10. Financial contributions ## 12. Financial contributions
Contact the maintainer by mail if you wish to make a financial contribution. Contact the maintainer by mail if you wish to make a financial contribution.

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

@@ -89,6 +89,11 @@ TERM=xterm-256color
# creates setfr, setus, setes. # creates setfr, setus, setes.
#SET_LOCALE=fr:fr_FR.UTF-8,us:en_US.UTF-8 #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.
# Example: DEFAULT_LANG=fr → calls setfr at startup.
# Leave unset to keep the system default locale.
#DEFAULT_LANG=fr
# ============================================================================== # ==============================================================================
[net] [net]
# dwl: Force a specific download tool (curl, wget, fetch). # dwl: Force a specific download tool (curl, wget, fetch).

View File

@@ -15,9 +15,6 @@ version-bump.
- [ ] **Bash completion** — add a `profile.d/completion/` directory and write - [ ] **Bash completion** — add a `profile.d/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]**
--- ---
@@ -70,10 +67,6 @@ version-bump.
(configurable via `MYEXTIP_FALLBACK_URL`) when the primary times out. (configurable via `MYEXTIP_FALLBACK_URL`) when the primary times out.
**[easy]** **[easy]**
### packages
- [ ] **Additional backends** — add support for `pacman` (Arch), `apk` (Alpine),
`xbps-query` (Void), and `brew` (macOS). **[medium]**
### processes ### processes
- [ ] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be - [ ] **`ku` dry-run flag** — add `-n` / `--dry-run` to print what would be
killed without acting. **[easy]** killed without acting. **[easy]**

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 # Compresse au format bz2
$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 # Compresse au format 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
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -179,5 +183,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

View File

@@ -39,6 +39,8 @@
# Usage: help # Usage: help
help() help()
{ {
# 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 "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"
@@ -72,6 +74,7 @@ help()
printf " * setc\tSet locale to standard C (POSIX)\n" printf " * setc\tSet locale to standard C (POSIX)\n"
printf " * set*\tLocale shortcuts generated from SET_LOCALE in profile.conf\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 "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 "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 "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 "taz\t\tCompress files and directories into a chosen archive format\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

@@ -70,9 +70,32 @@ dwl()
# 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"; } if [[ -z "$output" ]]; then
curl -sL "$url"
else
curl -sL -o "$output" "$url"
fi
}
_try_wget()
{
if [[ -z "$output" ]]; then
wget -qO- "$url"
else
wget -q -O "$output" "$url"
fi
}
_try_fetch()
{
if [[ -z "$output" ]]; then
fetch -o - "$url"
else
fetch -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,80 @@
# * 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-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 +149,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

@@ -164,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
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -191,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))
@@ -230,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

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

@@ -27,14 +27,14 @@ 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

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

@@ -34,9 +34,9 @@ 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

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

@@ -17,8 +17,8 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
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

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

@@ -17,7 +17,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
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

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

@@ -19,7 +19,7 @@
# 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)

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

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

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

@@ -26,9 +26,9 @@ 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

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

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

@@ -108,14 +108,14 @@ RESETCOL="\e[0m"
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

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
@@ -128,6 +129,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 +217,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

@@ -45,7 +45,7 @@ fi
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
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -66,17 +66,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 +98,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 +140,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 +169,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 +183,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 +207,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
@@ -258,11 +263,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.0.0