Bash (Українська)/Prompt customization (Українська)
У Bash існує кілька запрошень командного рядка, кожне з яких можна налаштувати на основі особистих уявлень про зручність та естетичність.
Запрошення
Bash має чотири рядки запрошення, кожен з яких може бути налаштований.
-
PS1
- головне запрошення, яке з'являється перед кожною командою; з цієї причини вона змінюється найчастіше. -
PS2
- Друге запрошення відображається, якщо команда вимагає введення додаткових даних (наприклад, у випадку багаторядкових команд). -
PS3
використовується рідко. З'являється, коли виконується вбудована команда Bashselect
, і відображається інтерактивне меню. На відміну від інших запрошень, не розкриває. Зазвичай всі зміни застосовуються безпосередньо до скрипту, що міститьselect
, а не до файлу. bashrc
. -
PS4
- також рідко використовується. При налагодженні скриптів відображаються рівні вкладеності - перший символ запрошення повторюється стільки разів, скільки в даний час є активних рівнів.
Встановлення конкретного запрошення передбачає призначення (зазвичай у файлі ~/.bashrc
) потрібного рядка змінній, наприклад:
PS2='> '
Техніки
Завжди можна зробити запрошення явним, але є ряд прийомів, які роблять його більш динамічним і корисним.
Escape-послідовності Bash
Коли рядок запрошення виводиться, Bash шукає символи втечі (послідовності втечі) і перетворює їх у спеціальні рядки. Наприклад, \u
перетвориться в ім'я користувача, а \A
- в поточний час.Таким чином, якщо змінній PS1
призначити '\A \u $ '
, то запрошення буде виглядати так :
17:35 користувач $
Весь список escape-послідовностей можна знайти в керівництві bash(1) § PROMPTING та довіднику Bash.
Escape-послідовності terminfo
Крім escape-послідовностей, які розуміє Bash, більшість терміналів також розпізнають спеціальні послідовності, які впливають на термінал сам собою, а не на друковані символи. Наприклад, можна змінити колір рядка символів, зрушити курсор у довільну позицію або очистити екран. Ці послідовності можуть бути досить незручними та варіюються від терміналу до терміналу, тому вони задокументовані у базі даних terminfo. Щоб побачити, які властивості підтримує термінал, виконайте:
$ infocmp
Значення властивостей можна знайти в terminfo(5) за назвами (частина перед =). Наприклад, властивість setaf
налаштовує колір шрифту для тексту, який буде надрукований після нього. Дізнатися про escape-код властивості можна командою tput
. Наприклад,
$ tput setaf 2
виведе escape-послідовність для налаштування зеленого кольору шрифту.
TERM
має правильне значення для терміналу. Наприклад, якщо встановлено значення xterm
замість xterm-256color
, то tput setaf
працюватиме лише з номерами кольорів 0-7.На практиці, щоб використовувати ці можливості у запрошенні командного рядка, можна використовувати підстановку команд Bash та інтерполяцію рядків. Наприклад:
GREEN="\[$(tput setaf 2)\]" RESET="\[$(tput sgr0)\]" PS1="${GREEN}my prompt${RESET}> "
\[ \]
. Це допоможе Bash правильно враховувати недруковані символи під час обчислення довжини запрошення. Під час встановлення команд це не працює, тому використовуйте значення \1 \2
.Escape-послідовності ANSI
На жаль, ANSI-послідовності можуть бути відсутні в базі terminfo вашого терміналу. Найчастіше це стосується послідовностей для нових можливостей на кшталт підтримки 256 кольорів. У цьому випадку використовувати tput не вийде і доведеться вводити escape-послідовність вручну.
Приклади escape-послідовностей можна знайти у статті Керувальні послідовності ANSI.Кожна послідовність починається з літералу escape-послідовності, яку можна ввести за допомогою escape-послідовності Bash \e
. Наприклад, \e[48;5;209m
задасть персиковий колір фону (якщо є підтримка 256 кольорів), а \e[2;2H
зрушить курсор у лівий верхній кут екрана.
Якщо escape-послідовності Bash не підтримуються (як у запрошенні PS3), їх можна додати командою printf:
ESC = $ (printf "e") PEACH="$ESC[48;5;209m"
Вбудовані команди
Якщо ви хочете додати висновок якоїсь команди на запрошення, то використовуйте підстановку команд (command substitution). Наприклад, щоб додати величину вільної пам'яті до запрошення, спробуйте щось на зразок:
PS1="$(awk '/MemFree/{print $2}' /proc/meminfo) prompt > "
53718 prompt > 53718 prompt > 53718 prompt >
Як бачимо, це працює не зовсім коректно - значення пам'яті завжди одне й те саме! Причина — команда виконується лише один раз при першому налаштуванні PS1. Необхідно запобігти підстановці або екрануванням символу $
, або визначенням рядка в одиночних лапках — в обох випадках підстановка буде проводитися щоразу при відображенні запрошення:
PS1="\$(awk '/MemFree/{print \$2}' /proc/meminfo) prompt > " # или PS1='$(awk "/MemFree/{print \$2}" /proc/meminfo) prompt > '
Якщо команди зробили запрошення надто довгим, для кращої читабельності можна винести їх у функцію:
free_mem() { awk '/MemFree/{print $2}' /proc/meminfo } PS1='$(free_mem) prompt > '
\[ \]
не буде працювати при обрамленні ними рядка з символами, що не друкуються. Натомість використовуйте восьмеричні екрановані послідовності \001
і \002
(наприклад, у командах printf
або echo -e
).
PROMPT_COMMAND
Змінною PROMPT_COMMAND
можна надати довільну команду, яка буде виконуватися безпосередньо перед виведенням PS1. Це дозволяє створювати досить сильні ефекти. Наприклад, можна перепризначити PS1 на основі деяких умов або виконати якісь дії з історією Bash під час виконання будь-якої команди.
PROMPT_COMMAND
не повинна використовуватися для виведення символів безпосередньо на запрошення. Символи, надруковані поза PS1, не враховуються Bash, що може призвести до неправильного позиціонування курсору та звичайних символів. Або використовуйте PROMPT_COMMAND
для завдання PS1, або вивчіть рекомендації у розділі #Вбудовані команди.
PROMPT_COMMAND
стала надто складною, bash-preexec (реалізація хук-функцій preexec
і precmd
ssh].Escape-послідовності між введенням та виведенням
Властивості тексту можна змінити, "забувши" відключити властивості в кінці PS1. Наприклад, якщо вставити tput blink
в кінець PS1, то команди, що вводяться, мерехтіть. Проте цей ефект також перейде і на виведення команди, оскільки властивості не відключаються при натисканні Enter
.
Щоб вставити escape-послідовність після введення, але перед початком виведення можна перехопити (trap) Bash-сигнал DEBUG, який посилається перед виконанням кожної команди:
$ trap 'tput sgr0' DEBUG
Налаштування запрошення root
Для зручності можна зробити запрошення командного рядка root-користувача візуально відмінним від звичайного (можливо мерехтливий червоний колір?). Налаштування запрошення здійснюється як завжди, але в домашньому каталозі суперкористувача /root
. Почніть з копіювання шаблонів /etc/skel/.bash_profile
та /etc/skel/.bashrc
до каталогу /root
, після чого внесіть у файл /root/.bashrc
необхідні зміни.
Приклади
Кольори
infocmp
містить доступну для tput
кількість кольорів, наприклад - colors#8
.Побачити всі кольори вашого терміналу можна за допомогою простого циклу (замініть setab
на setaf
, якщо потрібен колір тексту, а не тла):
for C in {0..255}; do tput setab $C echo -n "$C " done tput sgr0 echo
Якщо це не працює (причому встановлено правильне значення TERM), протестуйте вручну різні послідовності:
# стандартні кольори for C in {40..47}; do echo -en "\e[${C}m$C " done # кольори високої інтенсивності for C in {100..107}; do echo -en "\e[${C}m$C " done # 256 кольорів for C in {16..255}; do echo -en "\e[48;5;${C}m$C " done echo -e "\e(B\e[m"
Аналогічні значення для тексту (не фону): стандартні - 30..37
, висока інтенсивність - 90..97
, а для 256 кольорів замініть 48 на 38.
Основні властивості
Наступні властивості terminfo будуть корисні при налаштуванні запрошення та підтримуються у багатьох терміналах. #1 і #2 необхідно замінити на числові аргументи.
Властивість | Escape-послідовність | Опис |
---|---|---|
Властивості тексту | ||
blink | \E[5m | мерехтливий тект вкл |
bold | \E[1m | напівжирний текст вкл |
dim | \E[2m | тьмяний текст вкл |
rev | \E[7m | зворотне відображення вкл (текст/фон змінюються кольорами) |
sitm | \E[3m | курсив вкл |
ritm | \E[23m | курсив викл |
smso | \E[7m | виділення тексту вкл |
rmso | \E[27m | виділення тексту викл |
smul | \E[4m | підкреслення вкл |
rmul | \E[24m | підкреслення викл |
setab #1 | \E[4#1m | встановити колір фону #1 (0-7) |
setaf #1 | \E[3#1m | задати колір тексту #1 (0-7) |
sgr0 | \E(B\E[m | відключити всі атрибути тексту |
Переміщення курсору | ||
sc | \E7 | зберегти позицію курсору |
rc | \E8 | повернути курсор у збережену позицію |
clear | \E[H\E[2J | очистити екран і перемістити курсор у лівий верхній кут |
cuu #1 | \E[#1A | перемістити курсор вгору на #1 рядків |
cud #1 | \E[#1B | перемістити курсор вниз #1 рядків |
cuf #1 | \E[#1C | перемістити курсор вправо #1 стовпців |
cub #1 | \E[#1D | перемістити курсор вліво #1 стовпців |
home | \E[H | перемістити курсор у лівий верхній кут вікна |
hpa #1 | \E[#1G | перемістити курсор у стовпець #1 |
vpa #1 | \E[#1d | перемістити курсор у рядок #1, перший стовпець |
cup #1 #2 | \E[#1;#2H | перемістити курсор у рядок #1, стовпець #2 |
Видалення символів | ||
dch #1 | \E#1P | видалити #1 символів (аналогічно натисканню клавіші backspace) |
dl #1 | \E#1M | видалити #1 рядків |
ech #1 | \E#1X | стерти #1 символів (без переміщення курсору) |
ed | \E[J | очистити до нижнього краю екрану |
el | \E[K | очистити до кінця рядка |
el1 | \E[1K | очистити до початку рядка |
Відображення коду виходу
Тим же прийомом, як у вбудованих команд, можна відкласти інтерполяцію спеціальної змінної Bash на кшталт $?
. Наступні запрошення матимуть код виходу попередньої команди:
PS1="\$? > " # или PS1='$? > '
0 > false
1 >
Це можна зробити за допомогою умовних виразів та функцій:
exitstatus() { if [[ $? == 0 ]]; then echo ':)' else echo 'D:' fi } PS1='$(exitstatus) > '
:) > false
D: >
Позиціонування курсору
Курсор можна переміщати по екрану під час знаходження "всередині" запрошення PS1, щоб різні частини запрошення з'являлися у різних місцях. Важливий момент – після всіх переміщень та виведення символів у будь-яких місцях екрана курсор необхідно повернути у вихідну позицію. Це можна зробити за допомогою властивостей sc
та rc
, які зберігають та відновлюють позицію курсору відповідно. Загальна схема запрошення, що містить переміщення курсору:
PS1="\[$(tput sc; переміщення курсора) робота з курсором $(tput rc)\] робота з курсором після повернення"
Весь блок з переміщеннями курсору обернутий в \[ \]
, щоб Bash не враховував символи, що не друкуються, як частина запрошення.
Вирівнювання по правому краю
Найпростіший спосіб надрукувати текст у правого краю екрана – використовувати printf:
rightprompt() { printf "%*s" $COLUMNS "right prompt" } PS1='\[$(tput sc; rightprompt; tput rc)\]left prompt > '
Тут встановлено поле %*s
змінної довжини з вирівнюванням по правому краю. Розмір поля дорівнює поточній кількості стовпців у терміналі ($COLUMNS
).
Довільне позиціонування
Властивість cup
переміщує курсор у конкретну позицію екрану, наприклад tput cup 20 5
перемістить курсор на рядок 20, стовпець 5 (координати 0 0 позначають верхній лівий кут). cuu
, cud
, cuf
і cub
(вгору, вниз, вперед, назад) переміщують курсор щодо поточної позиції. Наприклад, tput cuf 10
перемістить курсор на 10 символів праворуч. В аргументах можна використовувати змінні LINES
та COLUMNS
, якщо потрібно перемістити курсор щодо нижнього та правого країв вікна. Наприклад, переміщення на 10 рядків та 5 стовпців від правого нижнього кута:
$ tput cup $((LINES - 11)) $((COLUMNS - 6))
Налаштування назви вікна терміналу
Назву вікна терміналу можна налаштувати так само, як і запрошення: виведенням escape-послідовностей в оболонці. Часто користувачі вбудовують налаштування назви вікна у своє запрошення. Технічно це можливість xterm, а й інші сучасні термінали її підтримують. У цьому випадку використовують послідовності ESC]2;нова назва'BEL
, де ESC
і 'BEL
- символи escape (вихід) і bell (сигнал). З послідовностями Bash запрошення з вбудованою назвою вікна буде мати вигляд:
PS1='\[\e]2;нова назва\a\]prompt > '
Зрозуміло, що рядок назви вікна може включати висновок вбудованих команд або змінні на кшталт $PWD
, так що вона може переналаштовуватися після кожної команди.
Дивіться також
- Приклади та скріншоти на темі форуму: What's your PS1?
- Файл /etc/bash/bashrc для Gentoo; див. також gentoo-bashrcAUR[пакет відсутній: package not found]
- tput(1)
- Запрошення Bash HOWTO
- Колекція прикладів запрошень від Giles Orr
- Поради Bash: кольори та форматування
- Liquid Prompt – корисне адаптивне запрошення для Bash & zsh
- Bash POWER PROMPT
- Wikipedia - Керувальна послідовність
- Керівництво GNU Bash: керування запрошенням