TUI functions library in Bash
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
3.9 KiB

#!/usr/bin/env bash
# GLOBALS
declare UI_CROW UI_CCOL USER_INPUT
# TERMINAL AND CURSOR INFO
term_size() case $1 in
c) echo $(tput cols)
;;
l) echo $(tput lines)
;;
*) echo $(tput lines) $(tput cols)
esac
cursor_position() {
echo $UI_CROW $UI_CCOL
}
cursor_line() {
echo $UI_CROW
}
cursor_col() {
echo $UI_CCOL
}
# CURSOR POSITION
cursor_set() {
UI_CROW=$1
UI_CCOL=$2
tput cup $UI_CROW $UI_CCOL
}
cmove_top() {
UI_CROW=0
UI_CCOL=${1:-0}
cursor_set $UI_CROW $UI_CCOL
}
cmove_bottom() {
UI_CROW=$(( $(term_size l) - 1 ))
UI_CCOL=${1:-0}
cursor_set $UI_CROW $UI_CCOL
}
cmove_row() {
UI_CROW=$1
cursor_set $UI_CROW $UI_CCOL
}
cmove_col() {
UI_CCOL=$1
cursor_set $UI_CROW $UI_CCOL
}
cmove_up() {
local mv
mv=${1:-1}
: $((UI_CROW - $mv))
UI_CROW=$(( $_ >= 0 ? (UI_CROW - mv) : 0 ))
cmove_row $UI_CROW
}
cmove_down() {
local mv limit
mv=${1:-1}
limit=$(($(term_size l) - 1))
: $((UI_CROW + $mv))
UI_CROW=$(( $_ < limit ? (UI_CROW + mv) : limit ))
cmove_row $UI_CROW
}
cmove_left() {
local mv
mv=${1:-1}
: $((UI_CCOL - $mv))
UI_CCOL=$(( $_ >= 0 ? (UI_CCOL - mv) : 0 ))
cmove_col $UI_CCOL
}
cmove_right() {
local mv limit
mv=${1:-1}
limit=$(($(term_size c) - 1))
: $((UI_CCOL + $mv))
UI_CCOL=$(( $_ < limit ? (UI_CCOL + mv) : limit ))
cmove_col $UI_CCOL
}
cmove_home() {
UI_CCOL=0
cmove_col $UI_CCOL
}
cmove_end() {
UI_CCOL=$(($(term_size c) - 1))
cmove_col $UI_CCOL
}
# CLEAR TERMINAL, LINE AND REGION
clear_terminal() {
clear
UI_CROW=0
UI_CCOL=0
}
clear_line() {
UI_CROW=${1:-$(cursor_line)}
cursor_set $UI_CROW 0
tput el
}
clear_region() {
local row col width height fill line
row=$1
col=$2
width=$3
height=$((row + $4 - 1))
printf -v fill "%${width}s" ''
for line in $(seq -s ' ' $row $height ); do
cursor_set $line $col
printf '%s' "$fill"
done
}
# FRAMES AND WINDOWS
draw_frame() {
local row col width height fill line
row=$1
col=$2
width=$3
height=$((row + $4 - 2))
printf -v fill "%$((width - 2))s" ''
cursor_set $row $col
printf '%s' "${fill// /─}"
((row++))
for line in $(seq -s ' ' $row $height ); do
cursor_set $line $col
printf '%s' "${fill}"
((row++))
done
cursor_set $row $col
printf '%s' "${fill// /─}"
}
draw_title_bar() {
local fill
printf -v fill "%$(($3 - 2))s" ''
cursor_set $(( $1 + 2 )) $2
printf '%s' "${fill// /─}"
}
draw_status_bar() {
local fill
printf -v fill "%$(($3 - 2))s" ''
cursor_set $(($1 + $4 - 3)) $2
printf '%s' "${fill// /─}"
}
# STRINGS
print_label() {
local str align col_start col_end column line_width len
str="$1"
len=$(str_len "$str")
col_start=0
col_end=$(term_size c)
align=left
case $# in
2) if in_string 'left right center' "$2"; then
align=$2
else
col_start=${2%,*}
col_end=${2#*,}
fi
;;
3) align=$2
col_start=${3%,*}
col_end=$((${3#*,} + 1))
;;
esac
line_width=$(( col_end - col_start ))
case $align in
left) column=$col_start;;
right) column=$((col_start + line_width - len));;
center) column=$((col_start + ((line_width - len) / 2) ));;
esac
cursor_set $UI_CROW $column
printf '%s' "$str"
}
str_len() {
echo "${#1}"
}
in_string() [[ "$1" == *"$2"* ]]
# WIDGETS
input_bar() {
local prompt position border line
prompt="$1"
position=bottom
border=1
line=$(($(term_size l) - 3))
case $# in
2) in_string 'top bottom' "$2" && position=$2 || border=$2;;
3) position=$2; border=$3;;
esac
if ((border)); then
[[ $position = top ]] && line=0
draw_frame $line 0 $(term_size c) 3
cmove_up
cmove_right 2
else
case $position in
top) cmove_top 1;;
bottom) cmove_bottom 1;;
esac
fi
read -rep "$prompt " USER_INPUT
}