rain bug fix and new engine
This commit is contained in:
@@ -248,14 +248,14 @@ change the default without having to pass flags every time.
|
||||
|
||||
| Key | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `RAIN_DEFAULT_SPEED` | `0.1` | Falling speed for `rain` |
|
||||
| `RAIN_DEFAULT_COLOR` | `Green` | Colour for `rain` |
|
||||
| `RAIN_DEFAULT_SPEED` | `5` | Delay between frames for `rain`: a value ≥ 1 is in hundredths of a second (`5` = 0.05 s), a value < 1 is in seconds; must be > 0 |
|
||||
| `RAIN_DEFAULT_COLOR` | `white` | Colour for `rain` (`green`, `blue`, `red`, `yellow`, `cyan`, `white`; case-insensitive) |
|
||||
| `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` |
|
||||
| `RAINBOW_DEFAULT_SPEED` | `4` | Frame delay (hundredths of a second) of the colour shift for `rainbow` |
|
||||
| `MATRIX_DEFAULT_SPEED` | `3.5` | Frame delay for `matrix`, same scale as `RAIN_DEFAULT_SPEED` |
|
||||
| `MATRIX_DEFAULT_COLOR` | `green` | Colour for `matrix` (same names as `rain`) |
|
||||
| `MATRIX_DEFAULT_DENSITY` | dynamic | Maximum number of simultaneous falling elements for `matrix` |
|
||||
| `MATRIX_DEFAULT_CHARSET` | `binary` | Character set for `matrix` (`binary`, `kana`, `ascii`) |
|
||||
| `MATRIX_DEFAULT_CHARSET` | `binary` | Character set for `matrix` (`binary`, `kana`, `ascii`; case-insensitive) |
|
||||
|
||||
**`[ssh]`**
|
||||
|
||||
|
||||
@@ -140,6 +140,18 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
(they were evaluated as arithmetic expressions); `pwdscore` classifies
|
||||
characters with locale-proof classes; README default of
|
||||
`GENPWD_DEFAULT_OCCURS` corrected.
|
||||
- `rain.sh`: the terminal was left with the last drop colour active, the cursor
|
||||
parked over the frozen last frame and the user's `INT`/`TERM`/`WINCH` traps
|
||||
deleted and `stty` forced to `echo`: the screen is now cleared and the traps
|
||||
and terminal settings restored; a resize now clears the screen and drops
|
||||
(drops placed for the old size lingered); a drop vanished for one frame each
|
||||
time another one left the screen; each frame is written with one `printf`
|
||||
instead of one per character (output is byte-identical, a lot faster);
|
||||
colour and charset names are case-insensitive (`RAIN_DEFAULT_COLOR=Green`, as
|
||||
documented, fell back to white), an unknown colour is an error instead of a
|
||||
silent white, a null speed no longer spins the CPU, a non-terminal stdin or
|
||||
stdout is refused instead of looping, and the usage mentions `q` to quit;
|
||||
README defaults of the `[rain]` keys corrected.
|
||||
- `compress.sh`: option flags and loop variables no longer leak into the
|
||||
interactive shell.
|
||||
|
||||
|
||||
+164
-94
@@ -41,9 +41,19 @@ load_conf "rain"
|
||||
|
||||
_rain_build_colors()
|
||||
{
|
||||
local base_color="$1"
|
||||
# Case-insensitive: the configuration documents capitalised names (Green)
|
||||
local base_color="${1,,}"
|
||||
local i
|
||||
RAIN_ENGINE_COLORS=()
|
||||
|
||||
case "$base_color" in
|
||||
green|blue|red|yellow|cyan|white) ;;
|
||||
*)
|
||||
disp E "Unknown color: ${1} (supported: green, blue, red, yellow, cyan, white)."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local use_truecolor=0
|
||||
# term_set() already sets TERM=*-direct when truecolor is available;
|
||||
# honour COLORTERM as a belt-and-suspenders fallback.
|
||||
@@ -63,7 +73,7 @@ _rain_build_colors()
|
||||
*) r1=40; g1=40; b1=45; r2=220; g2=220; b2=255 ;;
|
||||
esac
|
||||
|
||||
local i r g b
|
||||
local r g b
|
||||
for ((i = 0; i < steps; i++)); do
|
||||
r=$(( r1 + (r2 - r1) * i / (steps - 1) ))
|
||||
g=$(( g1 + (g2 - g1) * i / (steps - 1) ))
|
||||
@@ -134,6 +144,12 @@ _rain_normalize_speed()
|
||||
return 1
|
||||
fi
|
||||
|
||||
# A null delay is refused: "read -t 0" does not wait, the animation loop
|
||||
# would spin and use a whole CPU.
|
||||
if LC_ALL=C awk -v s="$raw_speed" 'BEGIN { exit !(s == 0) }'; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if LC_ALL=C awk -v s="$raw_speed" 'BEGIN { exit !(s < 1) }'; then
|
||||
printf "%s" "$raw_speed"
|
||||
else
|
||||
@@ -205,6 +221,54 @@ _rainbow_build_palette()
|
||||
fi
|
||||
}
|
||||
|
||||
# Stop request of the animation loops: sets exit_st, a local of the running
|
||||
# animation (dynamic scoping). Installed as the TERM/INT trap.
|
||||
_rain_stop()
|
||||
{
|
||||
exit_st=1
|
||||
}
|
||||
|
||||
# The animations read a key from the terminal and draw on it, and need tput.
|
||||
# Usage: _rain_need_tty <command-name>
|
||||
_rain_need_tty()
|
||||
{
|
||||
if [[ ! -t 0 || ! -t 1 ]]; then
|
||||
disp E "$1: a terminal is required (standard input and output must be a terminal)."
|
||||
return 1
|
||||
fi
|
||||
command -v tput >/dev/null 2>&1 || {
|
||||
disp E "The program 'tput' is required but not installed."
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Prepare the terminal for an animation: save its settings and the TERM, INT
|
||||
# and WINCH traps of the caller, install the animation traps, disable echo,
|
||||
# hide the cursor and clear the screen.
|
||||
# saved_stty and saved_traps are locals of the calling animation.
|
||||
# Usage: _rain_enter <winch_handler_function>
|
||||
_rain_enter()
|
||||
{
|
||||
saved_stty=$(stty -g 2>/dev/null)
|
||||
saved_traps=$(trap -p TERM INT WINCH)
|
||||
trap _rain_stop TERM INT
|
||||
trap "$1" WINCH
|
||||
stty -echo
|
||||
printf '\e[?25l\e[2J'
|
||||
}
|
||||
|
||||
# Undo _rain_enter: reset the colours (the last drawn drop colour would
|
||||
# otherwise stay active), show the cursor, clear the screen, then restore the
|
||||
# terminal settings and the caller's traps.
|
||||
_rain_leave()
|
||||
{
|
||||
printf '\e[0m\e[?25h\e[2J\e[H'
|
||||
[[ -n "$saved_stty" ]] && stty "$saved_stty"
|
||||
trap - TERM INT WINCH
|
||||
[[ -n "$saved_traps" ]] && eval "$saved_traps"
|
||||
return 0
|
||||
}
|
||||
|
||||
_rain_engine()
|
||||
{
|
||||
local step_duration="$1"
|
||||
@@ -213,16 +277,14 @@ _rain_engine()
|
||||
local charset="$4"
|
||||
local density_override="$5"
|
||||
|
||||
command -v tput >/dev/null 2>&1 || {
|
||||
disp E "The program 'tput' is required but not installed."
|
||||
return 1
|
||||
}
|
||||
_rain_need_tty "$mode" || return 1
|
||||
|
||||
_rain_build_colors "$base_color"
|
||||
_rain_build_colors "$base_color" || return 1
|
||||
_rain_build_chars "$mode" "$charset" || return 1
|
||||
|
||||
local rain_colors=("${RAIN_ENGINE_COLORS[@]}")
|
||||
local rain_chars=("${RAIN_ENGINE_CHARS[@]}")
|
||||
unset RAIN_ENGINE_COLORS RAIN_ENGINE_CHARS
|
||||
local rain_color_tab=${#rain_colors[@]}
|
||||
local rain_tab=${#rain_chars[@]}
|
||||
local matrix_head_color=$'\e[1;97m'
|
||||
@@ -235,39 +297,48 @@ _rain_engine()
|
||||
local new_rain_odd=0 falling_odd=0
|
||||
local term_area=0
|
||||
local frame_sleep="$step_duration"
|
||||
local saved_stty="" saved_traps=""
|
||||
|
||||
sigwinch()
|
||||
# The drops: 5 consecutive entries each (X, Y of the top, character, colour,
|
||||
# length).
|
||||
local rains=()
|
||||
local num_rains=0
|
||||
local ch=""
|
||||
|
||||
# WINCH handler (and initial sizing). Called with the animation running, it
|
||||
# sees its locals through dynamic scoping.
|
||||
_rain_sigwinch()
|
||||
{
|
||||
term_width=$(tput cols)
|
||||
term_height=$(tput lines)
|
||||
((term_area = term_width * term_height))
|
||||
term_area=$(( term_width * term_height ))
|
||||
|
||||
case "$mode" in
|
||||
matrix)
|
||||
((max_rain_width = term_area / 3))
|
||||
((max_rain_height = term_height < 8 ? 1 : term_height / 6))
|
||||
((new_rain_odd = term_height > 50 ? 100 : term_height * 2))
|
||||
((new_rain_odd = new_rain_odd * 85 / 100))
|
||||
((falling_odd = 100))
|
||||
max_rain_width=$(( term_area / 3 ))
|
||||
max_rain_height=$(( term_height < 8 ? 1 : term_height / 6 ))
|
||||
new_rain_odd=$(( term_height > 50 ? 100 : term_height * 2 ))
|
||||
new_rain_odd=$(( new_rain_odd * 85 / 100 ))
|
||||
falling_odd=100
|
||||
|
||||
# Adapt cadence and density to terminal size for smoother rendering.
|
||||
if ((term_area < 1200)); then
|
||||
((max_rain_width = term_area / 4))
|
||||
max_rain_width=$(( term_area / 4 ))
|
||||
frame_sleep=$(LC_ALL=C awk -v s="$step_duration" 'BEGIN { printf "%.3f", s * 1.15 }')
|
||||
elif ((term_area > 5000)); then
|
||||
((max_rain_width = term_area / 2))
|
||||
max_rain_width=$(( term_area / 2 ))
|
||||
frame_sleep=$(LC_ALL=C awk -v s="$step_duration" 'BEGIN { printf "%.3f", s * 0.85 }')
|
||||
else
|
||||
frame_sleep="$step_duration"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
((max_rain_width = term_area / 4))
|
||||
((max_rain_height = term_height < 10 ? 1 : term_height / 10))
|
||||
((new_rain_odd = term_height > 50 ? 100 : term_height * 2))
|
||||
((new_rain_odd = new_rain_odd * 75 / 100))
|
||||
((falling_odd = term_height > 25 ? 100 : term_height * 4))
|
||||
((falling_odd = falling_odd * 90 / 100))
|
||||
max_rain_width=$(( term_area / 4 ))
|
||||
max_rain_height=$(( term_height < 10 ? 1 : term_height / 10 ))
|
||||
new_rain_odd=$(( term_height > 50 ? 100 : term_height * 2 ))
|
||||
new_rain_odd=$(( new_rain_odd * 75 / 100 ))
|
||||
falling_odd=$(( term_height > 25 ? 100 : term_height * 4 ))
|
||||
falling_odd=$(( falling_odd * 90 / 100 ))
|
||||
frame_sleep="$step_duration"
|
||||
;;
|
||||
esac
|
||||
@@ -275,16 +346,21 @@ _rain_engine()
|
||||
if [[ -n "$density_override" ]]; then
|
||||
max_rain_width="$density_override"
|
||||
fi
|
||||
|
||||
# The drops were placed for the previous size and the screen content
|
||||
# does not fit the new one: start again from an empty screen.
|
||||
rains=()
|
||||
num_rains=0
|
||||
printf '\e[2J'
|
||||
}
|
||||
|
||||
do_exit()
|
||||
# Draw one frame. The whole frame (erasing the previous drop positions,
|
||||
# then the new ones) is built in a string and written with one printf: a
|
||||
# write per character made the animation slow and flickering.
|
||||
_rain_render()
|
||||
{
|
||||
exit_st=1
|
||||
}
|
||||
|
||||
do_render()
|
||||
{
|
||||
local idx=0 y=0 drop_color="" current_char="" render_color=""
|
||||
local idx=0 y=0 drop_color="" current_char="" render_color="" out=""
|
||||
local esc=$'\e'
|
||||
|
||||
for ((idx = 0; idx < num_rains * num_rain_metadata; idx += num_rain_metadata)); do
|
||||
X=${rains[idx]}
|
||||
@@ -292,15 +368,19 @@ _rain_engine()
|
||||
drop_length=${rains[idx + 4]}
|
||||
for ((y = Y; y < Y + drop_length; y++)); do
|
||||
((y < 1 || y > term_height)) && continue
|
||||
printf "\e[%d;%dH " "$y" "$X"
|
||||
out+="${esc}[${y};${X}H "
|
||||
done
|
||||
done
|
||||
|
||||
for ((idx = 0; idx < num_rains * num_rain_metadata; idx += num_rain_metadata)); do
|
||||
if ((100 * RANDOM / 32768 < falling_odd)); then
|
||||
if ((++rains[idx + 1] > term_height)); then
|
||||
rains=("${rains[@]:0:idx}" "${rains[@]:idx+num_rain_metadata:num_rains*num_rain_metadata}")
|
||||
# The drop left the screen: remove it. The next drop moves
|
||||
# into this slot, which must be processed again (the loop
|
||||
# increment would skip it, and it would vanish for a frame).
|
||||
rains=("${rains[@]:0:idx}" "${rains[@]:idx+num_rain_metadata}")
|
||||
num_rains=$(( num_rains - 1 ))
|
||||
idx=$(( idx - num_rain_metadata ))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
@@ -324,27 +404,24 @@ _rain_engine()
|
||||
current_char="$rain_drop"
|
||||
render_color="$drop_color"
|
||||
fi
|
||||
printf "\e[%d;%dH%b%s" "$y" "$X" "$render_color" "$current_char"
|
||||
# render_color holds a literal \e[...m: hence %b below
|
||||
out+="${esc}[${y};${X}H${render_color}${current_char}"
|
||||
done
|
||||
done
|
||||
|
||||
[[ -n "$out" ]] && printf '%b' "$out"
|
||||
return 0
|
||||
}
|
||||
|
||||
trap do_exit TERM INT
|
||||
trap sigwinch WINCH
|
||||
stty -echo
|
||||
printf "\e[?25l"
|
||||
printf "\e[2J"
|
||||
|
||||
local rains=()
|
||||
local num_rains=0
|
||||
local ch=""
|
||||
|
||||
sigwinch
|
||||
_rain_enter _rain_sigwinch
|
||||
_rain_sigwinch
|
||||
while ((exit_st <= 0)); do
|
||||
read -r -n 1 -t "$frame_sleep" ch
|
||||
ch=""
|
||||
# A timeout makes read fail (status > 128): expected, not an error
|
||||
read -r -n 1 -t "$frame_sleep" ch || true
|
||||
case "$ch" in
|
||||
q|Q)
|
||||
do_exit
|
||||
_rain_stop
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -358,18 +435,16 @@ _rain_engine()
|
||||
fi
|
||||
X=$((term_width * RANDOM / 32768 + 1))
|
||||
Y=$((1 - drop_length))
|
||||
rains=("${rains[@]}" "$X" "$Y" "$rain_drop" "$drop_color" "$drop_length")
|
||||
rains+=("$X" "$Y" "$rain_drop" "$drop_color" "$drop_length")
|
||||
num_rains=$(( num_rains + 1 ))
|
||||
fi
|
||||
|
||||
do_render
|
||||
_rain_render
|
||||
done
|
||||
|
||||
printf "\e[%d;1H\e[0K" "$term_height"
|
||||
printf "\e[?25h"
|
||||
stty echo
|
||||
trap - TERM INT
|
||||
trap - WINCH
|
||||
_rain_leave
|
||||
unset -f _rain_sigwinch _rain_render
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -388,13 +463,14 @@ rain()
|
||||
printf "\t-d, --density NUM\tMaximum number of simultaneous falling elements.\n"
|
||||
printf "\t-c, --color COLOR\tSet the color theme (default: white).\n"
|
||||
printf "\t-h, --help\t\tDisplay this help message and exit.\n\n"
|
||||
printf "Available Colors:\n"
|
||||
printf "Available Colors (case-insensitive):\n"
|
||||
printf "\t\e[32mgreen\e[0m\t: Matrix-like green shades\n"
|
||||
printf "\t\e[34mblue\e[0m\t: Deep ocean blue gradients\n"
|
||||
printf "\t\e[31mred\e[0m\t: Crimson/Blood rain\n"
|
||||
printf "\t\e[33myellow\e[0m\t: Amber and gold tones\n"
|
||||
printf "\t\e[36mcyan\e[0m\t: Electric cyan/turquoise\n"
|
||||
printf "\twhite\t: Greyscale and white (original style)\n\n"
|
||||
printf "Press q (or Ctrl-C) to quit.\n"
|
||||
printf "Example: rain --color green --speed 3\n"
|
||||
}
|
||||
|
||||
@@ -413,13 +489,13 @@ rain()
|
||||
-s|--speed)
|
||||
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
|
||||
step_duration=$(_rain_normalize_speed "$2") || {
|
||||
disp E "--speed requires a numeric value."
|
||||
disp E "--speed requires a numeric value greater than 0."
|
||||
_rain_show_usage
|
||||
return 1
|
||||
}
|
||||
shift
|
||||
else
|
||||
disp E "--speed requires a numeric value."
|
||||
disp E "--speed requires a numeric value greater than 0."
|
||||
_rain_show_usage
|
||||
return 1
|
||||
fi
|
||||
@@ -486,6 +562,7 @@ matrix()
|
||||
printf "\t-c, --color COLOR\tSet color theme (default: green).\n"
|
||||
printf "\t-C, --charset SET\tCharacter set: binary, kana, ascii (default: binary).\n"
|
||||
printf "\t-h, --help\t\tDisplay this help message and exit.\n\n"
|
||||
printf "Press q (or Ctrl-C) to quit.\n"
|
||||
printf "Example: matrix -C kana -c green --speed 2\n"
|
||||
}
|
||||
|
||||
@@ -493,7 +570,9 @@ matrix()
|
||||
local step_duration
|
||||
step_duration=$(_rain_normalize_speed "$_raw_speed") || step_duration=0.035
|
||||
local base_color="${MATRIX_DEFAULT_COLOR:-green}"
|
||||
# Lower-cased, like the value of -C: the configuration may say "Kana"
|
||||
local charset="${MATRIX_DEFAULT_CHARSET:-binary}"
|
||||
charset="${charset,,}"
|
||||
local density_override="${MATRIX_DEFAULT_DENSITY:-}"
|
||||
|
||||
if [[ -n "$density_override" ]]; then
|
||||
@@ -505,13 +584,13 @@ matrix()
|
||||
-s|--speed)
|
||||
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
|
||||
step_duration=$(_rain_normalize_speed "$2") || {
|
||||
disp E "--speed requires a numeric value."
|
||||
disp E "--speed requires a numeric value greater than 0."
|
||||
_matrix_show_usage
|
||||
return 1
|
||||
}
|
||||
shift
|
||||
else
|
||||
disp E "--speed requires a numeric value."
|
||||
disp E "--speed requires a numeric value greater than 0."
|
||||
_matrix_show_usage
|
||||
return 1
|
||||
fi
|
||||
@@ -597,9 +676,8 @@ rainbow()
|
||||
local frame_sleep
|
||||
frame_sleep=$(_rain_normalize_speed "$_raw_speed") || frame_sleep=0.040
|
||||
|
||||
local -a _pargs=()
|
||||
readarray -td '' _pargs < <(printf '%s' "$PARSED" | xargs printf '%s\0')
|
||||
set -- "${_pargs[@]}"
|
||||
# Restore the getopt-normalised (shell-quoted) argument list
|
||||
eval set -- "$PARSED"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
@@ -611,12 +689,12 @@ rainbow()
|
||||
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"
|
||||
printf "Press q (or Ctrl-C) to quit.\n"
|
||||
return 0
|
||||
;;
|
||||
-s|--speed)
|
||||
frame_sleep=$(_rain_normalize_speed "$2") || {
|
||||
disp E "--speed requires a numeric value."
|
||||
disp E "--speed requires a numeric value greater than 0."
|
||||
return 1
|
||||
}
|
||||
shift 2
|
||||
@@ -632,18 +710,17 @@ rainbow()
|
||||
esac
|
||||
done
|
||||
|
||||
command -v tput >/dev/null 2>&1 || {
|
||||
disp E "The program 'tput' is required but not installed."
|
||||
return 1
|
||||
}
|
||||
_rain_need_tty rainbow || 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=""
|
||||
local row_line="" screen="" ch=""
|
||||
local saved_stty="" saved_traps=""
|
||||
|
||||
sigwinch()
|
||||
# WINCH handler (and initial sizing): rebuild the palette for the new width
|
||||
_rainbow_sigwinch()
|
||||
{
|
||||
term_width=$(tput cols)
|
||||
term_height=$(tput lines)
|
||||
@@ -657,52 +734,45 @@ rainbow()
|
||||
fi
|
||||
|
||||
palette_width=$term_width
|
||||
offset=0
|
||||
_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
|
||||
_rain_enter _rainbow_sigwinch
|
||||
_rainbow_sigwinch
|
||||
while ((exit_st <= 0)); do
|
||||
read -r -n 1 -t "$frame_sleep" ch
|
||||
ch=""
|
||||
# A timeout makes read fail (status > 128): expected, not an error
|
||||
read -r -n 1 -t "$frame_sleep" ch || true
|
||||
case "$ch" in
|
||||
q|Q)
|
||||
do_exit
|
||||
_rain_stop
|
||||
;;
|
||||
esac
|
||||
|
||||
# One row of colours, shifted by offset (col - offset is at least
|
||||
# 1 - palette_width, so adding palette_width makes it positive)
|
||||
row_line=""
|
||||
for ((col = 0; col < term_width; col++)); do
|
||||
idx=$((col - offset))
|
||||
while ((idx < 0)); do
|
||||
idx=$(( idx + palette_width ))
|
||||
done
|
||||
idx=$((idx % palette_width))
|
||||
idx=$(( (col - offset + palette_width) % palette_width ))
|
||||
row_line+="${RAINBOW_BG_PALETTE[idx]} "
|
||||
done
|
||||
row_line+=$'\e[0m'
|
||||
|
||||
# Every row is the same: the whole screen goes out in one write
|
||||
screen=""
|
||||
for ((row = 1; row <= term_height; row++)); do
|
||||
printf "\e[%d;1H%b" "$row" "$row_line"
|
||||
screen+="\e[${row};1H${row_line}"
|
||||
done
|
||||
printf '%b' "$screen"
|
||||
|
||||
((offset = (offset + 1) % palette_width))
|
||||
offset=$(( (offset + 1) % palette_width ))
|
||||
done
|
||||
|
||||
printf "\e[0m\e[2J\e[H"
|
||||
printf "\e[?25h"
|
||||
stty echo
|
||||
trap - TERM INT
|
||||
trap - WINCH
|
||||
_rain_leave
|
||||
unset -f _rainbow_sigwinch
|
||||
unset RAINBOW_BG_PALETTE
|
||||
return 0
|
||||
}
|
||||
export -f rainbow
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user