Избегайте непечатных символов в функции для приглашения Bash

22

В приглашении Bash (переменная PS1) я вызываю функцию, чтобы потенциально добавить текст в приглашение: export PS1="\u@\h \$(my_function) \$ "

Однако функция в приглашении содержит цветовые коды ANSI, которые меняются в зависимости от выходных данных функции (иногда красный, иногда зеленый). Добавление " \[" к переменной PS1 должно исключить эти коды как непечатные, но если я сделаю echoв функции, " \[" будет напечатано буквально в приглашении.

Как я могу избежать этих цветовых кодов ANSI из функции для использования в приглашении bash?

MidnightLightning
источник

Ответы:

34

Библиотека readline принимает \001и \002(ASCII SOH и STX ) в качестве непечатаемых разделителей текста. Они также работают в любом приложении, которое использует readline .

Из lib/readline/display.c:243в Баш исходного кода:

243 /* Current implementation:
244         \001 (^A) start non-visible characters
245         \002 (^B) end non-visible characters
246    all characters except \001 and \002 (following a \001) are copied to
247    the returned string; all characters except those between \001 and
248    \002 are assumed to be `visible'. */

Баш -специфический \[и \]которые фактически переведены на \001и \002на y.tab.c:7640.


Примечание: Если вы используете Баш «s printfили echo -e, если текст имеет \001или \002непосредственно перед номером, вы попали в Баше ошибку , которая заставляет его есть одна цифры слишком много при обработке восьмеричным ускользает - то есть, \00142будет интерпретироваться как восьмеричная 014 (с последующим ASCII "2") вместо правильного восьмеричного 01 (с последующим ASCII "42"). По этой причине используйте шестнадцатеричные версии \x01и \x02вместо.

grawity
источник
Это делает это! echo -e "\001\e[31m\002RED"работает как положено. Благодарность!
MidnightLightning
Извините, что воскресил ответ, но каков эквивалент тире / аш / ш?
Хош Садик
@ Боже, если они используют readline, \001и \002будут работать. В противном случае я не уверен. Например, Dash определенно не использует readline .
wjandrea
1

Вот хороший полный ответ. Я должен был сделать намного больше рыть, чтобы выяснить, куда \ 001 и т. Д. Должен был пойти. Надеюсь это поможет.

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

Как я это настроил, круглые скобки в git-ветке появляются только в том случае, если вы находитесь в git-ветке, иначе она пустая.

Дэн Л
источник
0

Основываясь на ответе Гравити , следующее будет включать управляющие последовательности ANSI в ASCII SOH( ^A) и STX( ^B), которые эквивалентны \[и \]соответственно:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

Используйте это как:

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

Или:

$ readline_ANSI_escape "$string"

В качестве бонуса, многократное выполнение функции не приведет к повторному запуску уже сброшенных управляющих кодов.

Том Хейл
источник
-2

Если вы хотите использовать их в приглашении, вам нужно сделать \[. Но если вы хотите использовать его в эхо, вы должны использовать \033[.

Wuffers
источник
Хммм ... Добавление \ 033 [перед командой ANSI ("\ e [31m") и \ 033] после того, как кажется, что следующий напечатанный символ в приглашении не печатается.
MidnightLightning
1
Вы не хотите делать \ 033] после этого. \ 033 [31m запускает цвет, после чего вам нужно установить его обратно с помощью \ 033 [0m
Wuffers