Я написал сценарий Python для замены "powerline" в качестве решения для терминала для себя здесь: https://github.com/diogobaeder/dotfiles/blob/master/.bash_prompt.py
Тогда все, что я делаю, это определить подсказку из вывода этого скрипта:
# in my ~/.bashrc
export PS1="\$(python ~/.bash_prompt.py)"
Сам скрипт отлично работает, я получаю приглашение командной строки, которое я хочу; Однако, поскольку для стилей, которые я там помещаю, нет обертывания, терминал (неважно, какая программа GUI-терминала я использую) не правильно вычисляет ширину приглашения, и когда я ввожу символы после подсказки, она не завершает их на новую строку сначала, полностью перезаписывая приглашение.
Теперь я знаю, что при стилизации моего запроса bash мне нужно избегать кодов стиля с помощью \[
и \]
так что bash учитывает, что они являются escape-последовательностями и правильно вычисляет ширину. Однако, если я поместил их в качестве оболочек для своих стилей в свой скрипт Python (см. esc_start
и esc_end
), я не могу заставить их правильно оценивать bash как "escape escape-последовательности", вместо этого я получаю печатные квадратные скобки с буквами. Если я затем выйду на Python и обратную косую черту (\\[
и \\]
), тогда я получаю невыпущенные литералы (\[
и \]
). Кажется, что Bash полностью игнорирует их как escape-последовательности для вычисления ширины подсказки.
Если, однако, я удаляю обратную косую черту в моей команде PS1 ($(python ~/.bash_prompt.py)
вместо \$(python ~/.bash_prompt.py)
), а затем помещая \[
и \]
качестве escape-последовательностей в моем Python (как esc_start
и esc_end
), тогда bash считает их правильными экранами и заканчивает завершающие строки, как ожидалось (т. esc_start
esc_end
через правую границу, она завершает линию, как ожидалось). Однако проблема с этим заключается в том, что удаление этой обратной косой черты из моего определения PS1 в .bashrc
заставляет сценарий запускаться только один раз за сеанс терминала, а не для каждой строки подсказки - так, например, если я в рабочем дереве Git и я перехожу из одной ветки в другую, она не показывает новую ветвь, как только команда заканчивается, вместо нее отображается старая ветка.
Позвольте мне привести несколько примеров того, что я имею в виду, что вы можете попробовать в своем собственном .bashrc
без моего сценария Python:
PS1="\[\033[31m\]\u@\h\[\033[0m\]$ " # This wraps lines correctly
PS1="\033[31m\u@\h\033[0m$ " # This makes the line overwrite the prompt
Итак, любые идеи о том, как справиться с bash и заставить его правильно понимать последовательности \[
и \]
, когда они печатаются с помощью скрипта Python, сохраняя при этом скрипт для каждой командной строки? Или, если это ограничение в bash, есть ли другой способ заставить его обернуть линию, когда она достигнет правой границы окна терминала?
Спасибо! Диого
[EDIT] Решение (спасибо, Гриша Левит!):
Это моя линия bashrc:
PROMPT_COMMAND='PS1="$(python ~/.bash_prompt.py)"'
И я снова добавил escapes (\[
и \]
) к моему скрипту, и теперь он работает отлично! :-)
Сначала Bash интерпретирует escape-последовательности в $PS1
и только потом обрабатывает подстановку команд и т.д.
Bash позволяет настраивать эти строки, вставляя несколько специальных символов с обратным слэшем, которые декодируются следующим образом [...] После того, как строка декодируется, она расширяется посредством расширения параметров, замены команд, арифметического расширения и удаления цитат [...]
- Справочное руководство Bash: управление запросом
Это означает, что любые специальные последовательности, напечатанные вашей командой, не будут интерпретироваться как цвета и т.д. Решение заключается в использовании $PROMPT_COMMAND
для изменения значения $PS1
, например:
PROMPT_COMMAND='PS1=$(python ~/.bash_prompt.py)'