added rainbow

This commit is contained in:
fatalerrors
2026-05-21 16:12:56 +02:00
parent d03ced93bf
commit 2c81a48fe9
4 changed files with 202 additions and 3 deletions

View File

@@ -116,6 +116,7 @@ A bar-style prompt showing current time, execution time of the last command
| `profile_upgrade` | updates | Upgrade profile to the latest version (git pull or archive) |
| `pwdscore` | pwd | Calculate the strength score of a given password |
| `rain` | rain | Console screensaver with falling-rain effect (multiple color themes) |
| `rainbow` | rain | Full-screen rainbow screensaver using only background colors, with horizontal color shifting |
| `rmhost` | ssh | Remove host (name and IP) from SSH known_hosts; supports `--all-users` as root |
| `rmspc` | filefct | Replace spaces in filenames with underscores (or a custom character) |
| `setc` | lang | Set locale to standard C (POSIX) |
@@ -189,6 +190,7 @@ change the default without having to pass flags every time.
| `RAIN_DEFAULT_SPEED` | `0.1` | Falling speed for `rain` |
| `RAIN_DEFAULT_COLOR` | `Green` | Colour for `rain` |
| `RAIN_DEFAULT_DENSITY` | dynamic | Maximum number of simultaneous falling elements for `rain` |
| `RAINBOW_DEFAULT_SPEED` | `0.04` | Horizontal color shift speed for `rainbow` |
| `MATRIX_DEFAULT_SPEED` | `0.05` | Falling speed for `matrix` |
| `MATRIX_DEFAULT_COLOR` | `Green` | Colour for `matrix` |
| `MATRIX_DEFAULT_DENSITY` | dynamic | Maximum number of simultaneous falling elements for `matrix` |

View File

@@ -233,6 +233,10 @@ TERM=xterm-256color
# Leave unset to keep the terminal-size-based dynamic default.
#RAIN_DEFAULT_DENSITY=80
# rainbow: Horizontal color shift speed — integer/100 gives seconds (4 → 0.04 s).
# Values < 1 are used as raw seconds.
#RAINBOW_DEFAULT_SPEED=4
# matrix: Falling speed.
#MATRIX_DEFAULT_SPEED=3.5

View File

@@ -89,6 +89,7 @@ help()
printf "profile_upgrade\tUpgrade profile to the latest version (git pull or archive)\n"
printf "pwdscore\tCalculate the strength score of a given password\n"
printf "rain\t\tConsole screensaver with falling-rain effect (multiple color themes)\n"
printf "rainbow\t\tFull-screen rainbow screensaver using background colors only\n"
printf "rmhost\t\tRemove host (name and IP) from SSH known_hosts; supports --all-users as root\n"
printf "rmspc\t\tReplace spaces in filenames with underscores (or a custom character)\n"
printf "setlocale\tSet console locale to any installed locale\n"

View File

@@ -121,6 +121,76 @@ _rain_normalize_density()
printf "%s" "$raw_density"
}
_rainbow_supports_truecolor()
{
case "${COLORTERM:-}" in
*truecolor*|*24bit*)
return 0
;;
esac
case "${TERM:-}" in
*direct*|*truecolor*)
return 0
;;
esac
return 1
}
_rainbow_build_palette()
{
local palette_width="$1"
local use_truecolor="$2"
local x=0 wheel_pos=0 band=0 blend=0
local red=0 green=0 blue=0
RAINBOW_BG_PALETTE=()
if (( palette_width < 1 )); then
RAINBOW_BG_PALETTE+=("\e[41m")
return 0
fi
if (( use_truecolor )); then
for ((x = 0; x < palette_width; x++)); do
wheel_pos=$((x * 1536 / palette_width))
band=$((wheel_pos / 256))
blend=$((wheel_pos % 256))
case "$band" in
0)
red=255; green=$blend; blue=0
;;
1)
red=$((255 - blend)); green=255; blue=0
;;
2)
red=0; green=255; blue=$blend
;;
3)
red=0; green=$((255 - blend)); blue=255
;;
4)
red=$blend; green=0; blue=255
;;
*)
red=255; green=0; blue=$((255 - blend))
;;
esac
RAINBOW_BG_PALETTE+=("\e[48;2;${red};${green};${blue}m")
done
else
local ansi_palette=(41 101 43 103 42 102 46 106 44 104 45 105)
local ansi_count=${#ansi_palette[@]}
for ((x = 0; x < palette_width; x++)); do
RAINBOW_BG_PALETTE+=("\e[${ansi_palette[x * ansi_count / palette_width]}m")
done
fi
}
_rain_engine()
{
local step_duration="$1"
@@ -152,7 +222,6 @@ _rain_engine()
local term_area=0
local frame_sleep="$step_duration"
local sigwinch
sigwinch()
{
term_width=$(tput cols)
@@ -194,13 +263,11 @@ _rain_engine()
fi
}
local do_exit
do_exit()
{
exit_st=1
}
local do_render
do_render()
{
local idx=0 y=0 drop_color="" current_char="" render_color=""
@@ -497,6 +564,131 @@ matrix()
_rain_engine "$step_duration" "$base_color" "matrix" "$charset" "$density_override"
}
export -f matrix
# ------------------------------------------------------------------------------
# Full-screen rainbow screensaver
# Usage: rainbow [OPTIONS]
rainbow()
{
local PARSED
PARSED=$(getopt -o hs: --long help,speed: -n 'rainbow' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"rainbow --help\" to display usage."
return 1
fi
local _raw_speed="${RAINBOW_DEFAULT_SPEED:-4}"
local frame_sleep
frame_sleep=$(_rain_normalize_speed "$_raw_speed") || frame_sleep=0.040
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "Usage: rainbow [OPTIONS]\n"
printf "Options:\n"
printf "\t-s, --speed NUM\tSet horizontal color shift speed (default: 4 => 0.040s).\n"
printf "\t\t\t\tValues >=1 use a /100 scale (4 => 0.04s).\n"
printf "\t\t\t\tValues <1 are interpreted as raw seconds.\n"
printf "\t-h, --help\t\tDisplay this help message and exit.\n\n"
printf "The rainbow fills the whole terminal with background colors only.\n"
printf "It uses truecolor when supported, otherwise ANSI bright backgrounds.\n"
printf "Press q to quit.\n"
return 0
;;
-s|--speed)
frame_sleep=$(_rain_normalize_speed "$2") || {
disp E "--speed requires a numeric value."
return 1
}
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"rainbow --help\" to display usage."
return 1
;;
esac
done
command -v tput >/dev/null 2>&1 || {
disp E "The program 'tput' is required but not installed."
return 1
}
local exit_st=0
local term_height=0 term_width=0
local use_truecolor=0
local offset=0 row=0 col=0 palette_width=0 idx=0
local row_line="" ch=""
sigwinch()
{
term_width=$(tput cols)
term_height=$(tput lines)
((term_width < 1)) && term_width=1
((term_height < 1)) && term_height=1
if _rainbow_supports_truecolor; then
use_truecolor=1
else
use_truecolor=0
fi
palette_width=$term_width
_rainbow_build_palette "$palette_width" "$use_truecolor"
}
do_exit()
{
exit_st=1
}
trap do_exit TERM INT
trap sigwinch WINCH
stty -echo
printf "\e[?25l"
printf "\e[2J"
sigwinch
while ((exit_st <= 0)); do
read -r -n 1 -t "$frame_sleep" ch
case "$ch" in
q|Q)
do_exit
;;
esac
row_line=""
for ((col = 0; col < term_width; col++)); do
idx=$((col - offset))
while ((idx < 0)); do
((idx += palette_width))
done
idx=$((idx % palette_width))
row_line+="${RAINBOW_BG_PALETTE[idx]} "
done
row_line+=$'\e[0m'
for ((row = 1; row <= term_height; row++)); do
printf "\e[%d;1H%b" "$row" "$row_line"
done
((offset = (offset + 1) % palette_width))
done
printf "\e[0m\e[2J\e[H"
printf "\e[?25h"
stty echo
trap - TERM INT
trap - WINCH
}
export -f rainbow
# ------------------------------------------------------------------------------
load_conf "rain"