Prompt и Tab-completion
В прошлом уроке мы сравнили shell-ы и выбрали bash как фундамент. Теперь — про то, что делает работу в shell приятной (или мучительной): prompt и tab-completion.
Prompt — это та строчка, которая встречает вас перед каждой командой: user@host:~$. Outo-of-the-box она выглядит сухо. Хороший prompt экономит время: показывает, в какой папке вы, в какой git-ветке, активен ли Python venv. Tab-completion — это автодополнение по Tab: набираете git che<Tab> и видите варианты git checkout, git cherry-pick.
В этом уроке настроим и то, и другое.
PS1: переменная prompt
В bash и zsh prompt задаётся переменной PS1 (Prompt String 1). Это просто строка, в которой могут быть специальные коды.
Базовый bash-prompt выглядит примерно так:
$ echo $PS1
\u@\h:\w\$
Это значит:
\u— имя пользователя (напримерlevoely)\h— имя хоста (напримерdev-server)\w— текущая директория (с заменой/home/userна~)\$— символ$для обычного пользователя или#для root
Полный список escape codes в man bash (раздел PROMPTING). Самые полезные:
Цвета задаются ANSI escape codes — \033[XXm, где XX — цвет. Например, зелёный текст: \033[32m. Сброс: \033[0m.
Пример красивого prompt с временем и цветами:
# В ~/.bashrc:
export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] [\@]\$ '
Получится: зелёный user@host, синяя папка, время в [12:34 pm], потом $ .
Очень важны \[ и \] вокруг цветовых кодов. Без них bash считает, что цветовые символы — часть видимого текста. Это ломает выравнивание prompt, особенно когда вы прокручиваете историю стрелками — курсор начинает прыгать в странные места.
PS1 в zsh — немного иначе
zsh использует свои placeholders, отличные от bash:
# В ~/.zshrc:
export PS1='%n@%m:%~ %# '
%n— username%m— hostname короткое%M— hostname полное%~— working dir с ~%#—%для user,#для root
Также zsh поддерживает условный синтаксис: %(?.[x].[ ]) — показать [x] если exit code предыдущей команды 0, иначе [ ].
Цвета в zsh проще: %F{green}текст%f (foreground color, без сложных escape codes).
export PS1='%F{green}%n@%m%f:%F{blue}%~%f %# '
kubectl: работа с кластером из командной строки Git-статус в prompt: ветка и состояние
Starship: prompt будущего
Писать свой PS1 руками — это занятие на полдня, и потом ещё неделю крутить, чтобы выглядело хорошо. Альтернатива — starship.
Starship — это утилита, написанная на Rust, которая работает в любом shell (bash, zsh, fish, nushell, PowerShell). Она:
- Запускается перед каждой командой, собирает контекст (git, venv, k8s, время выполнения).
- Выводит готовый prompt в stdout, прокрашенный и форматированный.
- Настраивается через один
~/.config/starship.toml.
Установка на 30 секунд:
# Поставить
$ curl -sS https://starship.rs/install.sh | sh
# Активировать для bash (в ~/.bashrc):
$ echo 'eval "$(starship init bash)"' >> ~/.bashrc
# Для zsh:
$ echo 'eval "$(starship init zsh)"' >> ~/.zshrc
# Перезапустить shell
$ exec bash
Базовая конфигурация starship уже хороша. Если хотите кастомизировать — ~/.config/starship.toml:
# Минималистичный prompt
add_newline = false
format = "$directory$git_branch$git_status$python$character"
[character]
success_symbol = "[->](bold green)"
error_symbol = "[->](bold red)"
[git_branch]
symbol = " "
Полная документация — на starship.rs/config. Десятки модулей, сотни опций. Но что важно — конфиг ОДИН на всё ПК. Переносите между bash/zsh/fish — prompt выглядит одинаково.
Powerlevel10k: zsh-only альтернатива
Для тех, кто на zsh, есть Powerlevel10k (p10k). Это zsh-only тема, написанная нативно для zsh, поэтому супер-быстрая (запуск shell за 50ms vs 200ms у oh-my-zsh themes).
# Установка с oh-my-zsh:
$ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
# В ~/.zshrc заменить ZSH_THEME:
ZSH_THEME="powerlevel10k/powerlevel10k"
# Перезапустить shell — запустится wizard
$ exec zsh
Wizard за 2 минуты настроит prompt: цвета, иконки (Nerd Fonts), модули. Результат — production-grade prompt с git, k8s, venv и всем остальным.
Что выбрать: starship или p10k?
- starship — если работаете в нескольких shell-ах (bash на сервере, zsh локально). Конфиг переносится.
- p10k — если живёте только в zsh, нужна максимальная скорость. Wizard удобнее, чем starship config.
Для большинства DE я бы советовал starship — он работает везде.
Tab-completion: автодополнение по Tab
Когда вы набираете команду и нажимаете Tab, shell пытается дополнить. Это называется completion.
Базовое completion из коробки:
- Имена файлов и папок (
cd ~/Docu<Tab>->cd ~/Documents/) - Имена команд (
pyt<Tab>->python3)
Это в любом shell. Но интересное начинается с programmable completion — когда completion умеет «понимать» аргументы конкретной программы.
# git с completion
$ git che<Tab>
checkout cherry cherry-pick
$ git checkout <Tab>
HEAD main feature/api origin/main
# docker
$ docker run --<Tab>
--add-host --cap-add --cpu-period --detach
--attach --cap-drop --cpu-quota --device
...
Это работает потому, что git и docker предоставляют «completion definitions» — файлы, которые рассказывают shell-у, какие аргументы у команды.
Установка bash-completion
В bash programmable completion идёт через пакет bash-completion. На Ubuntu/Debian обычно установлен по умолчанию. Если нет:
$ sudo apt install -y bash-completion
# В ~/.bashrc должно быть (обычно уже есть):
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
Перезапустите shell, и git/docker/systemctl/kubectl автодополнения заработают.
На macOS:
$ brew install bash-completion@2
# В ~/.bashrc:
$ echo '[[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && . "/opt/homebrew/etc/profile.d/bash_completion.sh"' >> ~/.bashrc
В zsh completion из коробки лучше bash. oh-my-zsh добавляет плагины для git, docker, kubectl — это всё работает без дополнительной возни.
Как работает completion под капотом
Это интересно. Когда вы нажимаете Tab после git che, bash:
- Видит, что вы дополняете аргумент команды
git. - Ищет файл с completion для
git(обычно в/usr/share/bash-completion/completions/git). - Запускает функцию из этого файла, передав ей контекст (текущее слово, предыдущее слово, позицию курсора).
- Функция возвращает массив возможных вариантов.
- Bash показывает их в столбик.
Можно посмотреть, какие completion-функции зарегистрированы:
$ complete -p | head -5
complete -F __start_kubectl kubectl
complete -F _git git
complete -F _docker docker
complete -F __pip_complete pip3
complete -F __pip_complete pip
Каждая строка — это привязка функции (_git) к команде (git). Когда вы пишете свои bash-функции, можно подключить их к completion через complete -F your_func your_command.
Полезные completion-хитрости
Многие современные CLI генерируют completion автоматически. Стоит включить:
# kubectl
$ kubectl completion bash > ~/.kube/completion.bash
$ echo "source ~/.kube/completion.bash" >> ~/.bashrc
# docker (если ещё не работает)
$ docker completion bash > ~/.docker/completion.bash
# terraform
$ terraform -install-autocomplete
# poetry, pip, helm, awscli — все имеют completion bash
После этого Tab будет показывать что угодно: имена контекстов kubectl, имена секретов в AWS, провайдеров terraform.
Особенно полезно: kubectl get pod <Tab> показывает имена pod-ов в текущем namespace. kubectl logs <Tab> — то же. Вы не вбиваете руками 30-символьное имя airflow-worker-7f9b8c-x4kpt, а нажимаете Tab — оно дополняется. Это экономит часы в неделю.
Попробуй сам
Включите bash-completion если ещё не включён:
$ which complete 2>/dev/null || echo "completion не настроен"
# Список зарегистрированных completion-функций
$ complete -p | wc -l
156
# Попробуйте git completion:
$ git che<Tab><Tab> # двойной Tab показывает все варианты
checkout cherry cherry-pick
Поставьте starship и посмотрите, как меняется prompt:
$ curl -sS https://starship.rs/install.sh | sh
$ echo 'eval "$(starship init bash)"' >> ~/.bashrc
$ exec bash
# Зайдите в git-репо:
$ cd ~/some-git-repo
# В prompt появится ветка и статус
# Активируйте python venv:
$ python3 -m venv .venv && source .venv/bin/activate
# В prompt появится имя venv
Кастомизируйте PS1 руками (если не используете starship):
# В ~/.bashrc:
export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] \$ '
$ source ~/.bashrc
levoely@dev-server:~/linux-sandbox $