Привет, представляю вашему вниманию небольшой туториал по оформлению приглашения командной строки с эффектом красных глаз.
Все кто работал в консоли какого-нибудь Линукса наверно отмечали удобную особенность отображать текущую папку, имя пользователя, имя сервера и что-то еще в зависимости от дистра в строке приглашения. Мне тоже это всегда нравилось. Но иногда получалось вот так:
Сложно творить в строке из трех символов, конечно курсор переходит на следующую строку но это скорей еще больше бесит чем помогает. И вот в какой-то момент я сказал себе:
Я решил вернуть себе все пространство командной строки и больше не отдавать никому и никогда. Встал вопрос, как изменить текст приглашения командной строки? Оказалось, очень просто, достаточно изменить специальную системную переменную `PS1`.
Да, прямо в терминале можно задать новый текст приглашения. Но как сохранить изменения? Да и без информации о текущем каталоге как-то неуютно себя чувствуешь, постоянно задаешь себе вопрос: Где я? Поможет файл ~/.bashrc, в нём можно сохранить изменение PS1, а чтобы информация о текущей директории не занимала рабочее пространство, я решил разместить её не В а НАД командной строкой. Добавим в файл ~/.bashrc строку:
PS1='$PWD\n# '
Обратите внимания на одинарные кавычки, если мы используем двойные, то вместо указателя на переменную $PWD (системная переменная, в которой храниться полный путь текущей папки, аналог команда pwd) в строку приглашения запишется ее значение(текущий каталог) и меняться при переходе из папки в папку не будет. Выглядит это так:
Командная строка полностью свободна, но имя папки сливается с содержимым если выполнить команду ls. Придется отделить
printf -v line "%${COLUMNS}s"
Эта команда создаст переменную $line и заполнит её пробелами в количестве $COLUMNS но нам нужны не пробелы а "-", для этого используем следующий трюк:
line=${line// /-} # заменить все пробелы на -
Добавим этот код в ~/.bashrc
printf -v line "%${COLUMNS}s"line=${line// /-}PS1='\n$line\n$PWD\n$line\n# '
Отлично, но если сейчас изменить размер окна терминала, размер линий не изменится и красота пропадет:
Чтобы поправить ситуацию перенесем новый код в функцию info и добавим её в PS1:
info () { printf -v line "%${COLUMNS}s" line=${line// /-} printf "\n$line\n$PWD\n$line\n# "}PS1='$(info)'
Можно совместить приятное с полезным, добавив в верхний ограничитель вставку с именем хоста. Вставка с именем будет посередине, для этого нам необходимо вычислить центр линии(с учетом длинны названия хоста и доп. символов):
info () { name_lenght="{ $HOSTNAME }" name_lenght=${#name_lenght} top_line_left=$[(COLUMNS-name_lenght)/2] top_line_right=$[COLUMNS-(top_line_left+name_lenght)] printf -v top_line "%${top_line_left}s{_S_${HOSTNAME}_S_}%${top_line_right}s" printf -v bot_line "%${COLUMNS}s" bot_line=${bot_line// /-} top_line=${top_line// /-} top_line=${top_line//_S_/ } printf "\n$top_line\n$PWD\n$bot_line\n# "}PS1='$(info)'
Я заключил имя хоста в фигурные скобки с пробелами, но вместо пробелов вокруг $HOSTNAME используются символы "_S_" которые затем меняются на пробелы. Это необходимо потому, что в итоговой строке все пробелы заменяются на "-", а внутри вставки должны остаться пробелы. Добавим красок, для этого подготовим переменные с кодами изменения цвета текста в терминале, я использовал такие цвета:
RED='\e[31m' # красныйGRN='\e[32m' # зелёныйYLW='\e[33m' # жёлтыйBLU='\e[34m' # синийMGN='\e[35m' # пурпурныйDEF='\e[0m' # вернуть значения по умолчаниюBLD='\e[1m' # жирноDIM='\e[2m' # тускло
Добавим эти переменные в наш код:
info () { name_lenght="{ $HOSTNAME }" name_lenght=${#name_lenght} top_line_left=$[(COLUMNS-name_lenght)/2] top_line_right=$[COLUMNS-(top_line_left+name_lenght)] printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME${DEF}_S_$GRN}%${top_line_right}s" printf -v bot_line "%${COLUMNS}s" bot_line=$GRN${bot_line// /-}$DEF top_line=${top_line// /-} top_line=$GRN${top_line//_S_/ }$DEF printf "\n$top_line\n$BLD$BLU$PWD$DEF\n$bot_line\n# "}PS1='$(info)'
Идем дальше, правая часть выглядит пусто, можно разместить там дату, и время:
printf -v date "%(%a %d %b %T)T"
Чтобы разместить это справа необходимо добавить какое-то количество пробелов после $PWD, какое, давайте посчитаем:
center_space=$[COLUMNS-${#date}-${#PWD}]((center_space<0)) && center_space=1...printf "\n$top_line\n$BLD$BLU$PWD$DEF%${center_space}s$DIM$date\n$bot_line\n# "
Можно ли сделать лучше? Конечно, добавим вывод git status если находимся в папке с git проектом:
git_tst= git_clr= [[ -d .git ]] && { git_tst=(GIT $(git status -sb)) git_tst="${git_tst[*]} " # простой для теста git_clr=(GIT $(git -c color.ui=always status -sb)) git_clr="${git_clr[*]} " # цветной для вывода } ... center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}] ... printf "\n$top_line\n$BLD$BLU$PWD$DEF%${center_space}s${git_clr[*]}$DIM$date\n$bot_line\n\$ "
Обратите внимания что git_clr и git_tst сначала записываются массивом, а затем преобразуются в переменные. Это необходимо для того чтобы удалить переходы строки из вывода git status. Но где же глаза? Сейчас будут глаза О_о, создадим массив с базовым набором глаз:
eyes=(O o )
И посчитаем их количество:
en=${#eyes[@]}
Добавим символ рта:
mouth='_'
И сделаем генератор случайных морд:
face () { printf "$YLW${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}$DEF"}
Глаза будут находиться по краям информационного поля, необходимо учесть их при расчете количества пробелов в середине, подготовим для этого отдельную переменную:
face_tst='O_o o_O'...center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}-${#face_tst}]printf "\n$top_line\n$(face) $BLD$BLU$PWD$DEF%${center_space}s$git_clr$DIM$date $(face)\n$bot_line\n\$ "
Как заставить глаза покраснеть?
info () { error=$? ...}
И изменим функцию face таким образом, чтобы она проверяла переменную $error и в зависимости от её значения красила глаза в красный или жёлтый:
face () { [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"}
Ну вот
[[ $debian_chroot ]] && chrt="($debian_chroot)" || chrt=...name_lenght="{ $HOSTNAME$chrt }"...printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME$chrt${DEF}_S_$GRN}%${top_line_right}s"
И изменим текст в заголовке окна терминала:
PS1='$(info)'; case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;$(face 1) \w\a\]$PS1";; esac
В заголовок будет выводится морда и текущий каталог, но придется немного доработать функцию face чтобы она рисовала морду без цветовых кодов, они в заголовке бутут отображаться просто текстом, передадим функции face какой-нибудь параметр (например 1), внутри функции добавим проверку, если задан 1-й аргумент, выдать морду без разукрашивания:
face () { [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW [[ $1 ]] && printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" \ || printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"}
Итоговый скрипт:
RED='\e[31m' # красныйGRN='\e[32m' # зелёныйYLW='\e[33m' # жёлтыйBLU='\e[34m' # синийMGN='\e[35m' # пурпурныйDEF='\e[0m' # вернуть значения по умолчаниюBLD='\e[1m' # жирноDIM='\e[2m' # тусклоeyes=(O o ) en=${#eyes[@]} mouth='_'face () { [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW [[ $1 ]] && printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" \ || printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"}info () { error=$? git_tst= git_clr= [[ -d .git ]] && { git_tst=(GIT $(git status -sb)) git_tst="${git_tst[*]} " # простой для теста git_clr=(GIT $(git -c color.ui=always status -sb)) git_clr="${git_clr[*]} " # цветной для вывода } [[ $debian_chroot ]] && chrt="($debian_chroot)" || chrt= name_lenght="{ $HOSTNAME$chrt }" name_lenght=${#name_lenght} face_tst='O_o o_O' top_line_left=$[(COLUMNS-name_lenght)/2] top_line_right=$[COLUMNS-(top_line_left+name_lenght)] printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME$chrt${DEF}_S_$GRN}%${top_line_right}s" printf -v bot_line "%${COLUMNS}s" printf -v date "%(%a %d %b %T)T" top_line=${top_line// /-} top_line=$GRN${top_line//_S_/ }$DEF bot_line=$GRN${bot_line// /-}$DEF center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}-${#face_tst}] ((center_space<0)) && center_space=1 printf "\n$top_line\n$(face) $BLD$BLU$PWD$DEF%${center_space}s$git_clr$DIM$date $(face)\n$bot_line\n\$ "}PS1='$(info)'; case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;$(face 1) \w\a\]$PS1";; esac
На этом все, спасибо за внимание!) Подписывайтесь, ставьте лайки, вот это вот все, проект есть в гитхабе info-bar Творите, выдумывайте, пробуйте!)