Learning Platform
Глоссарий Troubleshooting
Урок 04.03 · 18 мин
Начальный
BashZshPromptPS1CompletionStarship

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). Самые полезные:

Escape codes для PS1 в bash
\uUsername — кто вы. Например, 'levoely'
\h / \HHostname короткое (до первой точки) / полное
\w / \WWorking dir полный с ~ для home / только базовое имя последней папки
\t / \T / \@Время в 24h / 12h / 12h с am/pm
\d / \D{fmt}Дата по локали / по strftime-формату, например \\D{%Y-%m-%d}
\$$ для user, # для root. Визуально показывает, что вы под root, а не обычным юзером
\!Номер команды в истории (от 1). Полезно для !N reuse
\\nПеренос строки. Полезно для многострочных prompt с длинным путём
\\[ \\]Маркеры начала/конца невидимых символов (цветовые escape codes). Без них bash считает символы цвета как видимые и ломает выравнивание

Цвета задаются 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], потом $ .

WARNING

Очень важны \[ и \] вокруг цветовых кодов. Без них 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). Она:

  1. Запускается перед каждой командой, собирает контекст (git, venv, k8s, время выполнения).
  2. Выводит готовый prompt в stdout, прокрашенный и форматированный.
  3. Настраивается через один ~/.config/starship.toml.
Что показывает starship в prompt
Текущая папкаПокажет, в какой папке. Если внутри git-репозитория — путь относительно корня репо
git-ветка + statusИмя ветки, статус (clean [x], modified !, untracked ?, staged +). Цвета меняются от статуса
Python venvИмя активного virtualenv (например, 'airflow-dev'). Если venv не активен — ничего не показывает
kubectl contextТекущий k8s контекст и namespace. Полезно: видишь, куда деплоишь, до того как сделаешь kubectl apply -f prod.yaml
Docker contextЕсли работаете с несколькими Docker-окружениями (locally vs remote)
Время выполненияЕсли предыдущая команда выполнялась больше N миллисекунд — показывает время. Так видно, какие команды медленные
Exit codeЕсли предыдущая команда вернула ≠0 — показывает код красным. Видишь, какие команды упали
JobsЕсли в background есть процессы (jobs) — показывает их количество
...modulesДесятки других модулей: Go, Rust, Node.js, AWS, Azure, dotnet, и т.д. Все опциональные

Установка на 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:

  1. Видит, что вы дополняете аргумент команды git.
  2. Ищет файл с completion для git (обычно в /usr/share/bash-completion/completions/git).
  3. Запускает функцию из этого файла, передав ей контекст (текущее слово, предыдущее слово, позицию курсора).
  4. Функция возвращает массив возможных вариантов.
  5. 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.

Что происходит при нажатии Tab
Вы набралиТекущее состояние: команда + позиция курсора
Tab
BashСмотрит зарегистрированную completion-функцию для команды git
_git()Bash-функция из /usr/share/bash-completion/completions/git. Знает, что 'che' — это начало подкоманды git
Выводcheckout, cherry, cherry-pick — все subcommands начинающиеся с 'che'

Полезные 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.

TIP

Особенно полезно: 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 $

Проверка знанийKnowledge check
Junior настроил красивый PS1 с цветами, но prompt 'прыгает' при прокрутке истории стрелками: курсор оказывается в странных местах. В чём проблема?
ОтветAnswer
Junior забыл обернуть цветовые ANSI-коды в \[ и \]. Эти маркеры говорят bash: 'это невидимые символы, не считай их при расчёте длины prompt'. Без них bash думает, что цветовые escape-последовательности (например \033[01;32m, это 7 видимых символов) — это видимый текст, и неправильно считает позицию курсора. Когда вы листаете историю, bash думает, что курсор в одной позиции, а на самом деле в другой. Правильный PS1: export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\w \$ '. Все цветовые коды в \[...\]. Альтернатива — использовать starship или powerlevel10k, они корректно обрабатывают это автоматически.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что задаёт PS1 в bash?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4