Як включити команди в PS1 Баша, не порушуючи обчислення довжини рядка?


13

Тонін вказав на помилку в моєму запиті за замовчуванням . Мінімальний приклад:

  1. Встановити PS1:

    PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " ")$ '

    На даний момент підказка виглядає приблизно так:

    $ 
  2. Тепер запустіть вихідний код запуску:

    false

    Тепер підказка містить вихідний код червоним кольором на початку рядка:

    1 $ 
  3. Натисніть Ctrl- r.
  4. Введіть "false". Тепер запит містить лише пошук:

    (reverse-i-search)`false': false
  5. Натисніть Enter.

Отримана історія терміналу тепер містить наступне:

1 $ch)`false': false

Очікуваний вихід:

1 $ false

Тобто, схоже, що результат пошуку історії змішується з підказкою та приховує фактичну команду, яку виконували.

Я спробував обійти це, використовуючиPROMPT_COMMAND :

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " "
}
set_bash_prompt() {
    PS1='$(set_exit_code)$ ' # Double quotes give the same result
}
PROMPT_COMMAND=set_bash_prompt

Схоже, це не працює - лінія виглядає точно так само, як і раніше після пошуку та запуску.

Як я можу це виправити?


1
Це, здається, є продовженням unix.stackexchange.com/a/71012
manatwork

Відповіді:


8

Я знайшов відповідь на askubuntu.com . @qeirha згадав, що ви повинні сказати bash, що послідовність символів не слід рахувати в довжині підказки, і ви робите це, додаючи її \[ \]. На основі наведеного прикладу, ось одне рішення:

red=$(tput setaf 1)

reset=$(tput sgr0)

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$red\] $exit_code \[$reset\] " ")$ '

Немає необхідності переходити до Спросити Ubuntu . На це питання ми вже маємо достатньо відповідей.
манастирство

Дякую за пораду @manatwork! Я хотів дати належну оцінку поясненням і подав посилання як люб’язно.
Тимофій Мартін

Надання кредиту не є проблемою. Але в той час як мова про проблему: незбиті накидки, котрі використовуються для зникнення з Маркдаун, тож ваш звичайний \ [став [у вашій публікації, таким чином відображений код не функціонував, копіюючи його в термінал. Цього можна уникнути, використовуючи вбудований код або розмітку блоку коду. ( Як я відформатую свої публікації за допомогою Markdown або HTML? )
manatwork

1
D'oh! Я вже виправив ту саму проблему для іншого PS1коду, чому я не бачив цього?
l0b0

1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(Вибачте, тут немає пояснень. Див. Як правильно налаштувати PS1? Або будь-яке інше питання щодо питань швидкого обчислення довжини та \[... \])


До другого запитання @ l0b0 я додам, що використання PS1 \[...\]працює добре, доки ви можете ввести весь код, який потрібно створити підказку, в одну рядок. Однак, якщо ви хочете розділити свій код на невеликі функції, ви доходите до того, що ви не можете поставити стартові та кінцеві дужки в один рядок / функцію. І це порушує обертання рядків. Якщо ви не вдаєтеся до використання PROMPT_COMMANDдля перерахунку своїх PS1при кожному запиті.
Тонін

1

Розширюючи відповідь на @manatwork, але зберігаючи код, розбиваючи PS1обчислення на різні функції, ви можете написати своє запит наступним чином:

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf "\[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] "
}
set_bash_prompt() {
    PS1="$(set_exit_code)$ " # with double quotes!
}
PROMPT_COMMAND=set_bash_prompt

Подвійні лапки є обов'язковими як при встановленні, так PS1і при використанні printfу функції.


Для подальшої довідки використовуйте функцію bash у своєму .bashrc- не вкладайте код в окремий файл і викликайте це.
starbeamrainbowlabs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.