wgctl/core/ui.sh
Nuno Duque Nunes 8bb1de4976 init feature
2026-05-19 15:26:31 +00:00

127 lines
No EOL
3.1 KiB
Bash

#!/usr/bin/env bash
UI_ROW_WIDTH=${UI_ROW_WIDTH:-20}
UI_SECTION_WIDTH=${UI_SECTION_WIDTH:-44}
function ui::row() {
local label="$1" value="$2" width="${3:-$UI_ROW_WIDTH}"
printf " %-${width}s %s\n" "${label}:" "$value"
}
function ui::section() {
local title="$1" width="${2:-$UI_SECTION_WIDTH}"
local dashes
dashes=$(printf '─%.0s' $(seq 1 $(( width - ${#title} - 4 ))))
printf "\n \033[0;37m── %s %s\033[0m\n" "$title" "$dashes"
}
function ui::list_item() {
local prefix="$1" value="$2"
printf " %s %s\n" "$prefix" "$value"
}
function ui::print_list() {
local prefix="$1" input="$2"
[[ -z "$input" ]] && return 0 # early return for empty input
while IFS= read -r e; do
[[ -n "$e" ]] && ui::list_item "$prefix" "$e"
done <<< "$input"
}
function ui::divider() {
local width="${1:-48}"
printf " %s\n" "$(printf '─%.0s' $(seq 1 $width))"
}
function ui::pad() {
local text="$1" width="${2:-20}"
local visible
visible=$(echo -e "$text" | sed 's/\x1b\[[0-9;]*m//g')
local pad=$(( width - ${#visible} ))
printf "%b%${pad}s" "$text" ""
}
function ui::pad_mb() {
local text="$1" width="${2:-20}"
local visible
visible=$(printf "%b" "$text" | sed 's/\x1b\[[0-9;]*m//g')
local vis_len
vis_len=$(python3 -c "import sys; print(len(sys.stdin.read().rstrip('\n')))" \
<<< "$visible")
local pad=$(( width - vis_len ))
[[ $pad -lt 0 ]] && pad=0
printf "%b%${pad}s" "$text" ""
}
function ui::vis_len_multi() {
# Get visible lengths of multiple strings in one Python call
# Returns newline-separated integers
python3 -c "
import sys, re
ansi = re.compile(r'\x1b\[[0-9;]*m')
for s in sys.argv[1:]:
print(len(ansi.sub('', s)))
" "$@"
}
function ui::pad_status() {
ui::pad "${1:-}" "${2:-25}"
}
function ui::center() {
local text="$1" width="${2:-8}"
local len=${#text}
local pad=$(( (width - len) / 2 ))
local rpad=$(( width - len - pad ))
printf "%${pad}s%s%${rpad}s" "" "$text" ""
}
function ui::firewall_rule() {
local rule="$1"
if [[ "$rule" =~ ACCEPT|DNAT ]]; then
printf "\033[0;32m%s\033[0m\n" "$rule"
elif [[ "$rule" =~ DROP ]]; then
printf "\033[0;31m%s\033[0m\n" "$rule"
elif [[ "$rule" =~ NFLOG|LOG ]]; then
printf "\033[0;37m%s\033[0m\n" "$rule"
else
printf "%s\n" "$rule"
fi
}
# ============================================
# Content Helpers
# ============================================
function ui::has_content() {
# Returns 0 (true) if content exists, 1 if empty
# Works with strings, arrays, or command output
local value="${1:-}"
[[ -n "$value" ]]
}
function ui::skip_if_empty() {
# Usage: ui::skip_if_empty "$var" || return 0
# Or: ui::skip_if_empty "${array[*]}" || return 0
local value="${1:-}"
[[ -z "${value// }" ]] && return 1 || return 0
}
function ui::empty() {
# ui::empty "$var" && return 0
# ui::empty "${array[*]}" && return 0
[[ -z "${1// }" ]]
}
# ============================================
# Prompt
# ============================================
function ui::confirm() {
local prompt="${1:-Are you sure?}"
local response
printf " %s [y/N] " "$prompt"
read -r response
[[ "${response,,}" == "y" || "${response,,}" == "yes" ]]
}