Захотелось мне как-то оформить башевский скрипт, чтобы выдавал менюшку в красивой рамочке. Погуглил, почесал репу, ну и накатал пару небольших функций. Результатом, с удовольствием, делюсь с участниками SO, вдруг кому пригодится.
Ответ
Вот что получилось:
declare -A C # Массив значений цветов
def_colors ()
{
C[Black]='\e[30m'
C[Red]='\e[31m'
C[Green]='\e[32m'
C[Yellow]='\e[33m'
C[Blue]='\e[34m'
C[Magenta]='\e[35m'
C[Cyan]='\e[36m'
C[LGray]='\e[37m'
C[Default]='\e[39m'
C[DGray]='\e[90m'
C[LRed]='\e[91m'
C[LGreen]='\e[92m'
C[LYellow]='\e[93m'
C[LBlue]='\e[94m'
C[LMagenta]='\e[95m'
C[LCyan]='\e[96m'
C[White]='\e[97m'
C[Normal]='\e[0m'
}
draw_line ()
{
local position="$1"
local width_line="$2"
local repeat="$4"
local left_position="$3"
local line_simbol='\u2501'
local line left_indent spacer
[[ $width_line -ne 0 ]] && spacer="\e[${width_line}C"
[[ $left_position -ne 0 ]] && left_indent="\e[${left_position}C"
case "$position" in
--top)
left_corner='\u250F'
right_corner='\u2513'
;;
--bottom)
left_corner='\u2517'
right_corner='\u251B'
;;
--blank)
left_corner='\u2503'
right_corner='\u2503'
;;
--box-separator)
left_corner="\u2523"
right_corner="\u252B"
;;
esac
if [[ "$position" == '--blank' ]]; then
while read -r;do
line+="${left_indent}${left_corner}${spacer}${right_corner}
"
done < <(seq "$repeat")
printf '%b' "$line"
else
while read -r;do
line+="$line_simbol"
done < <(seq "$width_line")
printf '%b%b%b%b
' "${left_indent}" "$left_corner" "$line" "$right_corner"
fi
}
draw_frame ()
{
local footer_height frame_color frame_height frame_width
local top_position left_position restore_position start_write
local terminal_width
terminal_width=$(tput cols)
local terminal_hight
terminal_hight=$(tput lines)
until [[ "$#" -eq 0 ]]; do
case "$1" in
-t) if [[ "$2" =~ ^[0-9]+$ ]];then
if [[ "$2" -lt "$(( terminal_hight - 5 ))" ]];then
top_position="$2"
else
top_position="$(( terminal_hight - 5 ))"
fi
shift
else
if [[ -z "$2" ]]; then
top_position=0
else
echo 'Set a positive numeric value for the top position of frame'
fi
fi
;;
-l) if [[ "$2" =~ ^[0-9]+$ ]];then
if [[ "$2" -lt "$(( terminal_width - 2 ))" ]];then
left_position="$2"
else
left_position="$(( terminal_width - 2 ))"
fi
shift
else
if [[ -z "$2" ]]; then
left_position=0
else
echo 'Set a positive numeric value for the left position of frame'
fi
fi
;;
-w) if [[ "$2" =~ ^[0-9]+$ ]];then
if [[ "$2" -lt "$(( terminal_width - 2 ))" ]];then
frame_width="$2"
else
frame_width="$(( terminal_width - 2 ))"
fi
shift
else
echo 'Set a positive numeric value for the frame width'
tput cnorm
return 1
fi
;;
-h) if [[ "$2" =~ ^[0-9]+$ ]];then
if [[ "$2" -lt "$(( terminal_hight - 5 ))" ]];then
frame_height="$2"
else
frame_height="$(( terminal_hight - 5 ))"
fi
shift
else
echo 'Set a positive numeric value for the frame height'
tput cnorm
return 1
fi
;;
-c) if [[ "$2" =~ \\e\[[0-9]{1,2}m$ ]]; then
frame_color="$2"
shift
else
[[ "$2" ]] &&
{
[[ "$2" =~ ^- ]] || shift
}
fi
;;
-f) if [[ "$2" =~ ^[0-9]+$ ]];then
footer_height="$2"
shift
else
[[ "$2" ]] &&
{
[[ "$2" =~ ^- ]] || shift
}
footer_height=1
fi
;;
-r|--restore-position)
restore_position='1'
;;
-s|--start-write)
start_write='1'
;;
esac
shift
done
top_position=${top_position:-0}
left_position=${left_position:-0}
[[ "$start_write" ]] && restore_position=
[[ "${restore_position:-0}" -eq 1 ]] && tput sc # Сохраняем позицию курсора
tput civis
clear
tput cup "$top_position" 0
if [[ $(( frame_width + left_position )) -gt $(( terminal_width - 2 )) ]];then
frame_width=$(( terminal_width - left_position - 2 ))
fi
if [[ $(( frame_height + top_position )) -gt $(( terminal_hight - 5 )) ]];then
frame_height=$(( terminal_hight - top_position - 5 ))
fi
[[ "$frame_color" ]] && printf '%b' "$frame_color"
if [[ "$frame_width" ]] && [[ "$frame_height" ]]; then
draw_line --top "$frame_width" "$left_position"
draw_line --blank "$frame_width" "$left_position" "$frame_height"
[[ -n "$footer_height" ]] && \
draw_line --box-separator "$frame_width" "$left_position" && \
draw_line --blank "$frame_width" "$left_position" "$footer_height"
draw_line --bottom "$frame_width" "$left_position"
fi
[[ "$frame_color" ]] && printf '%b' '\e[0m'
[[ "${restore_position:-0}" -eq 1 ]] && {
tput rc # Восстановить позицию
}
[[ "$footer_height" ]] && (( footer_height++ ))
[[ "${start_write:-0}" -eq 1 ]] && \
printf '%b' \
"\\e[$(( frame_height + 1 + ${footer_height:-0} ))A\\e[$(( left_position + 1 ))C"
tput cnorm
}
-w Ширина рамки;
-h Высота рамки без учета футера;
-c Цвет рамки;
-f Высота футера;
Высота и ширина - это количества строк и символов, соответственно, которые можно вписать не зацепив саму рамку
Если опустить -f, то просто будет бокс без футера
Если опустить -с, то цвет рамки будет стандартным для вашего терминала
draw_frame -w 50 -h 20 -c ${C[Green]} -t 5 -l 5 -f 1
Все размеры в колонках и линиях терминала соответственно.
UPD
Немного доработал, теперь можно задавать позицию бокса относительно левого верхнего угла терминала:
-l сдвиг влево
-t сдвиг вниз
Плюс. Добавил две опции:
-r [--restore-position] - Возвращает курсор туда, где он находился до начала отрисовки
-s [--start-write] - Устанавливает курсор в левый верхний угол пустого поля фрейма
Комментариев нет:
Отправить комментарий