feat(cli): add height-aware compact outage schedule
This commit is contained in:
155
main.sh
155
main.sh
@@ -74,6 +74,7 @@ Options:
|
||||
Environment:
|
||||
NO_COLOR Disable ANSI colors when set
|
||||
COLUMNS Override the detected output width
|
||||
LINES Override the detected output height
|
||||
|
||||
Required commands: Bash 4.3+, curl, jq, and GNU date
|
||||
EOF
|
||||
@@ -415,6 +416,38 @@ terminal_columns() {
|
||||
printf '%s\n' "$columns"
|
||||
}
|
||||
|
||||
terminal_lines() {
|
||||
local lines="${LINES:-}"
|
||||
local terminal_size="" detected_lines=""
|
||||
|
||||
if [[ -z "$lines" ]] && command -v stty >/dev/null 2>&1; then
|
||||
if [[ -r /dev/tty ]]; then
|
||||
terminal_size="$(stty size 2>/dev/null </dev/tty || true)"
|
||||
fi
|
||||
if [[ -z "$terminal_size" && -t 2 ]]; then
|
||||
terminal_size="$(stty size <&2 2>/dev/null || true)"
|
||||
fi
|
||||
if [[ -z "$terminal_size" && -t 0 ]]; then
|
||||
terminal_size="$(stty size <&0 2>/dev/null || true)"
|
||||
fi
|
||||
read -r detected_lines _ <<<"$terminal_size"
|
||||
if [[ "$detected_lines" =~ ^[0-9]+$ ]]; then
|
||||
lines="$detected_lines"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$lines" ]] && command -v tput >/dev/null 2>&1; then
|
||||
lines="$(tput lines 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
if [[ ! "$lines" =~ ^[0-9]+$ ]]; then
|
||||
lines=24
|
||||
elif ((lines < 10)); then
|
||||
lines=10
|
||||
fi
|
||||
printf '%s\n' "$lines"
|
||||
}
|
||||
|
||||
color_setup() {
|
||||
RESET=""
|
||||
BOLD=""
|
||||
@@ -714,10 +747,29 @@ human_duration() {
|
||||
printf '%s\n' "$output"
|
||||
}
|
||||
|
||||
compact_reference() {
|
||||
local bill_id="$1"
|
||||
local outage_number="$2"
|
||||
local width="$3"
|
||||
local reference="$bill_id/$outage_number"
|
||||
local bill_width
|
||||
|
||||
if ((${#reference} <= width)); then
|
||||
printf '%s' "$reference"
|
||||
elif ((width > ${#outage_number} + 2)); then
|
||||
bill_width=$((width - ${#outage_number} - 2))
|
||||
printf '~%s/%s' "${bill_id: -bill_width}" "$outage_number"
|
||||
elif ((width > 1)); then
|
||||
printf '%s~' "${reference:0:width-1}"
|
||||
else
|
||||
printf '~'
|
||||
fi
|
||||
}
|
||||
|
||||
render_event() {
|
||||
local line="$1"
|
||||
local now_epoch="$2"
|
||||
local ignored phase start_epoch stop_epoch record type_label timing
|
||||
local columns="$2"
|
||||
local ignored phase start_epoch stop_epoch record type_label reference reference_width
|
||||
local -a fields
|
||||
|
||||
IFS=$'\t' read -r ignored phase start_epoch stop_epoch record <<<"$line"
|
||||
@@ -725,18 +777,24 @@ render_event() {
|
||||
type_label="EMERGENCY"
|
||||
[[ "${fields[8]}" == "true" ]] && type_label="PLANNED"
|
||||
|
||||
if [[ "$phase" == "ONGOING" ]]; then
|
||||
timing="ends in $(human_duration "$((stop_epoch - now_epoch))")"
|
||||
if ((columns >= 60)); then
|
||||
reference_width=$((columns - 47))
|
||||
reference="$(compact_reference "${fields[0]}" "${fields[1]}" "$reference_width")"
|
||||
printf '%s%-9s%s %s%-9s%s %-10s %-11s %s\n' \
|
||||
"$([[ "$phase" == "ONGOING" ]] && printf '%s' "$RED" || printf '%s' "$CYAN")" \
|
||||
"$phase" "$RESET" \
|
||||
"$([[ "$type_label" == "PLANNED" ]] && printf '%s' "$GREEN" || printf '%s' "$YELLOW")" \
|
||||
"$type_label" "$RESET" "${fields[3]}" "${fields[4]}-${fields[5]}" "$reference"
|
||||
else
|
||||
timing="starts in $(human_duration "$((start_epoch - now_epoch))")"
|
||||
reference_width=$((columns - 34))
|
||||
((reference_width < 1)) && reference_width=1
|
||||
reference="$(compact_reference "${fields[0]}" "${fields[1]}" "$reference_width")"
|
||||
printf '%s%-4s%s %-5s %-10s %-11s %s\n' \
|
||||
"$([[ "$phase" == "ONGOING" ]] && printf '%s' "$RED" || printf '%s' "$CYAN")" \
|
||||
"$([[ "$phase" == "ONGOING" ]] && printf 'ON' || printf 'UP')" "$RESET" \
|
||||
"$([[ "$type_label" == "PLANNED" ]] && printf 'PLAN' || printf 'EMERG')" \
|
||||
"${fields[3]}" "${fields[4]}-${fields[5]}" "$reference"
|
||||
fi
|
||||
|
||||
printf '%s%s%-10s%s %s%-9s%s %s\n' \
|
||||
"$BOLD" "$([[ "$phase" == "ONGOING" ]] && printf '%s' "$RED" || printf '%s' "$CYAN")" \
|
||||
"$phase" "$RESET" "$([[ "$type_label" == "PLANNED" ]] && printf '%s' "$GREEN" || printf '%s' "$YELLOW")" \
|
||||
"$type_label" "$RESET" "$timing"
|
||||
printf ' Date %s %s - %s\n' "${fields[3]}" "${fields[4]}" "${fields[5]}"
|
||||
printf ' Reference bill %s / outage %s\n' "${fields[0]}" "${fields[1]}"
|
||||
}
|
||||
|
||||
render_empty() {
|
||||
@@ -780,7 +838,7 @@ draw_frame() {
|
||||
|
||||
if ((TERMINAL_ACTIVE)); then
|
||||
cleared_frame="${frame//$'\n'/$'\033[K\n'}"
|
||||
printf '\033[H%s\033[K\n\033[J' "$cleared_frame"
|
||||
printf '\033[H%s\033[K\033[J' "$cleared_frame"
|
||||
else
|
||||
printf '%s\n' "$frame"
|
||||
fi
|
||||
@@ -806,13 +864,17 @@ render_dashboard() {
|
||||
local now_epoch="$1"
|
||||
local columns="${2:-}"
|
||||
local countdown_bill_id="${3:-}"
|
||||
local rule phase start_epoch stop_epoch record remaining banner
|
||||
local schedule_line ignored
|
||||
local lines="${4:-}"
|
||||
local rule phase start_epoch stop_epoch record remaining banner banner_art
|
||||
local banner_rows fixed_rows available_rows visible_count hidden_count index show_bill_heading=0
|
||||
|
||||
color_setup
|
||||
if [[ -z "$columns" ]]; then
|
||||
columns="$(terminal_columns)"
|
||||
fi
|
||||
if [[ -z "$lines" ]]; then
|
||||
lines="$(terminal_lines)"
|
||||
fi
|
||||
|
||||
if ((${#SCHEDULE[@]} == 0)); then
|
||||
render_empty "$columns"
|
||||
@@ -834,29 +896,69 @@ render_dashboard() {
|
||||
remaining=$((start_epoch - now_epoch))
|
||||
fi
|
||||
banner="$(banner_duration "$remaining")"
|
||||
if [[ -n "$countdown_bill_id" ]]; then
|
||||
banner_art="$(print_large_countdown "$banner" "$columns")"
|
||||
banner_rows="$(awk 'END { print NR }' <<<"$banner_art")"
|
||||
[[ -n "$countdown_bill_id" ]] && show_bill_heading=1
|
||||
fixed_rows=$((8 + banner_rows))
|
||||
((show_bill_heading)) && fixed_rows=$((fixed_rows + 2))
|
||||
if ((fixed_rows + 2 > lines)); then
|
||||
banner_art="$banner"
|
||||
banner_rows=1
|
||||
fixed_rows=$((8 + banner_rows))
|
||||
((show_bill_heading)) && fixed_rows=$((fixed_rows + 2))
|
||||
if ((fixed_rows + 1 > lines)); then
|
||||
show_bill_heading=0
|
||||
fi
|
||||
fi
|
||||
if ((show_bill_heading)); then
|
||||
center_line "COUNTDOWN FOR BILL $countdown_bill_id" "$columns"
|
||||
printf '\n'
|
||||
fi
|
||||
printf '%s%s' "$BOLD" "$YELLOW"
|
||||
print_large_countdown "$banner" "$columns"
|
||||
printf '%s\n' "$banner_art"
|
||||
printf '%s' "$RESET"
|
||||
fi
|
||||
|
||||
printf '\n%s%s%s\n' "$CYAN" "$rule" "$RESET"
|
||||
printf '\n%sOUTAGE SCHEDULE (%d)%s\n\n' "$BOLD" "${#SCHEDULE[@]}" "$RESET"
|
||||
printf '\n%sOUTAGE SCHEDULE (%d)%s\n' "$BOLD" "${#SCHEDULE[@]}" "$RESET"
|
||||
if ((columns >= 60)); then
|
||||
printf '%s%-9s %-9s %-10s %-11s %s%s\n' \
|
||||
"$BOLD" "STATUS" "TYPE" "DATE" "TIME" "BILL/OUTAGE" "$RESET"
|
||||
else
|
||||
printf '%s%-4s %-5s %-10s %-11s %s%s\n' \
|
||||
"$BOLD" "ST" "TYPE" "DATE" "TIME" "REF" "$RESET"
|
||||
fi
|
||||
printf '%s%s%s\n' "$DIM" "$(repeat_character '-' "$columns")" "$RESET"
|
||||
|
||||
for schedule_line in "${SCHEDULE[@]}"; do
|
||||
IFS=$'\t' read -r ignored phase start_epoch stop_epoch record <<<"$schedule_line"
|
||||
render_event "$schedule_line" "$now_epoch"
|
||||
printf '%s\n' "$DIM$(repeat_character '-' "$columns")$RESET"
|
||||
fixed_rows=$((8 + ${banner_rows:-1}))
|
||||
((show_bill_heading)) && fixed_rows=$((fixed_rows + 2))
|
||||
available_rows=$((lines - fixed_rows - 1))
|
||||
((available_rows < 0)) && available_rows=0
|
||||
visible_count="${#SCHEDULE[@]}"
|
||||
hidden_count=0
|
||||
if ((visible_count > available_rows)); then
|
||||
if ((available_rows > 0)); then
|
||||
visible_count=$((available_rows - 1))
|
||||
else
|
||||
visible_count=0
|
||||
fi
|
||||
hidden_count=$((${#SCHEDULE[@]} - visible_count))
|
||||
fi
|
||||
|
||||
for ((index = 0; index < visible_count; index++)); do
|
||||
render_event "${SCHEDULE[index]}" "$columns"
|
||||
done
|
||||
if ((hidden_count && available_rows > 0)); then
|
||||
printf '%s... %d more outage%s%s\n' \
|
||||
"$DIM" "$hidden_count" "$([[ "$hidden_count" == 1 ]] || printf 's')" "$RESET"
|
||||
fi
|
||||
printf '%s%s%s\n' "$CYAN" "$rule" "$RESET"
|
||||
}
|
||||
|
||||
main() {
|
||||
local now_epoch next_refresh=0 refresh_minutes=10 refresh_seconds state_ready=0
|
||||
local last_rendered=-1 next_transition=0 rebuild_schedule=0 frame key input_fd=0
|
||||
local display_columns countdown_bill_id=""
|
||||
local display_columns display_lines render_lines countdown_bill_id=""
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
@@ -962,9 +1064,14 @@ main() {
|
||||
fi
|
||||
|
||||
display_columns="$(terminal_columns)"
|
||||
display_lines="$(terminal_lines)"
|
||||
render_lines="$display_lines"
|
||||
if [[ -n "$REFRESH_ERROR" ]] && ((render_lines > 12)); then
|
||||
render_lines=$((render_lines - 2))
|
||||
fi
|
||||
frame="$(
|
||||
if ((state_ready)); then
|
||||
render_dashboard "$now_epoch" "$display_columns" "$countdown_bill_id"
|
||||
render_dashboard "$now_epoch" "$display_columns" "$countdown_bill_id" "$render_lines"
|
||||
else
|
||||
render_unavailable "$display_columns"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user