Уникайте символів, що не друкуються, у функції для запиту Bash


22

У запиті Bash (змінна PS1) я викликаю функцію, щоб потенційно додати текст до запиту: export PS1="\u@\h \$(my_function) \$ "

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

Як я можу уникнути цих кольорів ANSI у межах функції, яка використовується для запиту bash?

Відповіді:


34

Readline бібліотека приймає \001і \002(ASCII SOH і STX ) в недрукованих текстових роздільників. Вони також працюють у будь-якій програмі, що використовує лінію читання .

З 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.


Примітка. Якщо ви використовуєте bash ' printfабо echo -e, і якщо у вашому тексті є \001або \002безпосередньо перед числом, ви потрапите на баш- помилку, яка змушує його з'їсти одну цифру занадто багато при обробці восьмеричних втеч - тобто \00142буде інтерпретуватися як восьмерична 014 (далі - ASCII "2"), а не правильний восьмеричний 01 (далі - ASCII "42"). З цієї причини використовуйте шістнадцяткову версію \x01і \x02замість цього.


Це робить! echo -e "\001\e[31m\002RED"працює як очікувалося. Спасибі!
опівночіЗасвітлення

Вибачте, що воскресив відповідь, але який еквівалент на тире / зола / ш?
Хош Садік

@Hosh Якщо вони використовують readline \001і \002працюватимуть. Інакше я не впевнений. Наприклад, тире напевно не використовує лінію читання .
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

Виходячи з відповіді grawity , наступне буде додавати контрольні послідовності 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[.


Хммм ... Додавання \ 033 [перед командою ANSI ("\ e [31m") та \ 033] після того, як здається, що наступний друкований символ у запиті не друкується.
опівночіЛіття

1
Ви не хочете робити \ 033] після цього. \ 033 [31м починає колір, після цього потрібно встановити його назад з \ 033 [0m
Wuffers
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.