Naposledy aktivní 1 month ago

Revize a827b5b166937705e9550b84285dea808b4312d2

gistfile1.txt Raw
1#!/usr/bin/env bash
2
3UI_ROW_WIDTH=${UI_ROW_WIDTH:-20}
4UI_SECTION_WIDTH=${UI_SECTION_WIDTH:-44}
5
6function ui::row() {
7 local label="$1" value="$2" width="${3:-$UI_ROW_WIDTH}"
8 printf " %-${width}s %s\n" "${label}:" "$value"
9}
10
11function ui::section() {
12 local title="$1" width="${2:-$UI_SECTION_WIDTH}"
13 local dashes
14 dashes=$(printf '─%.0s' $(seq 1 $(( width - ${#title} - 4 ))))
15 printf "\n \033[0;37m── %s %s\033[0m\n" "$title" "$dashes"
16}
17
18function ui::list_item() {
19 local prefix="$1" value="$2"
20 printf " %s %s\n" "$prefix" "$value"
21}
22
23function ui::print_list() {
24 local prefix="$1" input="$2"
25 [[ -z "$input" ]] && return 0 # early return for empty input
26 while IFS= read -r e; do
27 [[ -n "$e" ]] && ui::list_item "$prefix" "$e"
28 done <<< "$input"
29}
30
31function ui::divider() {
32 local width="${1:-48}"
33 printf " %s\n" "$(printf '─%.0s' $(seq 1 $width))"
34}
35
36function ui::pad() {
37 local text="$1" width="${2:-20}"
38 local visible
39 visible=$(echo -e "$text" | sed 's/\x1b\[[0-9;]*m//g')
40 local pad=$(( width - ${#visible} ))
41 printf "%b%${pad}s" "$text" ""
42}
43
44function ui::pad_mb() {
45 local text="$1" width="${2:-20}"
46 local visible
47 visible=$(printf "%b" "$text" | sed 's/\x1b\[[0-9;]*m//g')
48 local vis_len
49 vis_len=$(python3 -c "import sys; print(len(sys.stdin.read().rstrip('\n')))" \
50 <<< "$visible")
51 local pad=$(( width - vis_len ))
52 [[ $pad -lt 0 ]] && pad=0
53 printf "%b%${pad}s" "$text" ""
54}
55
56function ui::vis_len_multi() {
57 # Get visible lengths of multiple strings in one Python call
58 # Returns newline-separated integers
59 python3 -c "
60import sys, re
61ansi = re.compile(r'\x1b\[[0-9;]*m')
62for s in sys.argv[1:]:
63 print(len(ansi.sub('', s)))
64" "$@"
65}
66
67
68function ui::pad_status() {
69 ui::pad "${1:-}" "${2:-25}"
70}
71
72function ui::center() {
73 local text="$1" width="${2:-8}"
74 local len=${#text}
75 local pad=$(( (width - len) / 2 ))
76 local rpad=$(( width - len - pad ))
77 printf "%${pad}s%s%${rpad}s" "" "$text" ""
78}
79
80function ui::firewall_rule() {
81 local rule="$1"
82 if [[ "$rule" =~ ACCEPT|DNAT ]]; then
83 printf "\033[0;32m%s\033[0m\n" "$rule"
84 elif [[ "$rule" =~ DROP ]]; then
85 printf "\033[0;31m%s\033[0m\n" "$rule"
86 elif [[ "$rule" =~ NFLOG|LOG ]]; then
87 printf "\033[0;37m%s\033[0m\n" "$rule"
88 else
89 printf "%s\n" "$rule"
90 fi
91}
92
93# ============================================
94# Content Helpers
95# ============================================
96
97function ui::has_content() {
98 # Returns 0 (true) if content exists, 1 if empty
99 # Works with strings, arrays, or command output
100 local value="${1:-}"
101 [[ -n "$value" ]]
102}
103
104function ui::skip_if_empty() {
105 # Usage: ui::skip_if_empty "$var" || return 0
106 # Or: ui::skip_if_empty "${array[*]}" || return 0
107 local value="${1:-}"
108 [[ -z "${value// }" ]] && return 1 || return 0
109}
110
111function ui::empty() {
112 local val="${1:-}"
113 # Empty string or whitespace only
114 [[ -z "${val// }" ]] && return 0
115 # Numeric zero
116 [[ "$val" =~ ^[0-9]+$ ]] && [[ "$val" -eq 0 ]] && return 0
117 return 1
118}
119
120# Usage: ui::bool "$value" [yes_label] [no_label]
121# Default labels: yes / no
122function ui::bool() {
123 local val="${1:-}" yes="${2:-yes}" no="${3:-no}"
124 [[ "$val" == "true" ]] && echo "$yes" || echo "$no"
125}
126
127# ============================================
128# Prompt
129# ============================================
130
131function ui::confirm() {
132 local prompt="${1:-Are you sure?}"
133 local response
134 printf " %s [y/N] " "$prompt"
135 read -r response
136 [[ "${response,,}" == "y" || "${response,,}" == "yes" ]]
137}