Страницы

Поиск по вопросам

понедельник, 1 октября 2018 г.

Рамка на bash с использованием символов из Unicode Box Drawing

Захотелось мне как-то оформить башевский скрипт, чтобы выдавал менюшку в красивой рамочке. Погуглил, почесал репу, ну и накатал пару небольших функций. Результатом, с удовольствием, делюсь с участниками 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] - Устанавливает курсор в левый верхний угол пустого поля фрейма

Комментариев нет:

Отправить комментарий