it-swarm.com.ru

bash Подскажите и повторяющиеся цвета внутри функции

У меня есть это в моем .bashrc:

LIGHTGREEN="\[\033[1;32m\]"
LIGHTRED="\[\033[1;31m\]"
WHITE="\[\033[0;37m\]"
RESET="\[\033[0;00m\]"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u\$(error_test)@\w$RESET \$ "

Это, кажется, делает вывод Shell точно:

username\[\]@~/

Экранирование [и] вокруг цветовых кодов отображается в моей подсказке. Если я удаляю управляющие коды из-за цветов, это работает, но тогда перенос строки bash терпит неудачу. 

Обратите внимание, что если PS1="LIGHTGREEN - whatever - $RESET" работает, то [и] не экранированы. Тем не менее, я хочу сделать это внутри функции, которая, кажется, проблема.

Я не могу найти хорошую документацию по этому вопросу. man echo даже не перечисляет опцию -e. Похоже, что у Bash много недокументированных, ручных знаний.

42
Andy Ray

Я нашел эту тему в поисках ответа, как установить цвет bash с помощью экранирования \[ \] из функции bash.

На самом деле есть решение. Bash позволяет генерировать PS1 Prompt каждый раз при отображении Prompt. 

set_bash_Prompt(){
    PS1="\[email protected]\h $(call_your_function) $>"
}

Prompt_COMMAND=set_bash_Prompt

Таким образом, PS1 будет интерпретироваться каждый раз, когда будет отображаться запрос, поэтому он будет вызывать функцию и правильно отображать все экранирующие последовательности, включая \[ \], которые важны для подсчета длины запроса (например, для правильной работы истории команд).

Надеюсь, это кому-нибудь поможет, так как я трачу полдня на решение этой проблемы.

48
thedk

Используйте \001 вместо \[ и \002 вместо \] и помните о последствиях использования Prompt_COMMAND, поскольку этот метод будет сбрасывать запрос каждый раз (что также может быть именно тем, что вам нужно).

Решение для bash Prompt, отображающее цвета внутри функции, объясняется здесь :

\[\] являются специальными только при назначении PS1, если вы их печатаете внутри функции, которая запускается, когда отображается подсказка, она не Работа. В этом случае вам нужно использовать байты \001 и \002

Существует также этот другой ответ который указывает в том же направлении:

специфичные для bash \[ и \] фактически переводятся в \001 и \002

Установка PS1 внутри функции, вызываемой Prompt_COMMAND, как предложено в принятом aswer, сбрасывает PS1 каждый раз, не позволяя другим сценариям легко изменять ваш Promtp (например, Python virtualnenv activ.sh ):

$ echo $PS1
<your PS1>
$ PS1="(TEST)$PS1"
$ echo $PS1
<(TEST) is not prepended to PS1 if you are using Prompt_COMMAND as it is reset>
22
archemiro

\[ и \] должны использоваться непосредственно в $PS*, а не просто выводить их через echo.

LIGHTGREEN="\033[1;32m"
LIGHTRED="\033[1;31m"
WHITE="\033[0;37m"
RESET="\033[0;00m"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u\[\$(error_test)\]@\w\[$RESET\] \$ "
7
Ignacio Vazquez-Abrams

Вот цветная часть кода выхода моего кода PS1 :

color_enabled() {
    local -i colors=$(tput colors 2>/dev/null)
    [[ $? -eq 0 ]] && [[ $colors -gt 2 ]]
}

BOLD_FORMAT="${BOLD_FORMAT-$(color_enabled && tput bold)}"
ERROR_FORMAT="${ERROR_FORMAT-$(color_enabled && tput setaf 1)}"
RESET_FORMAT="${RESET_FORMAT-$(color_enabled && tput sgr0)}"

# Exit code
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $BOLD_FORMAT $ERROR_FORMAT $exit_code $RESET_FORMAT " ")'

Снимок экрана (с одним анонимным путем к хранилищу Subversion): Color coded output

0
l0b0

Это будет работать нормально.

LIGHTGREEN="\e[32m"
LIGHTRED="\e[31m"
RESET="\e[0m"

error_test () {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}
export PS1=$(printf "$(error_test) $(whoami)@${RESET}$(pwd) ")
0
Luis Lavaire

Я понимаю, что это старая тема, но я только что начал работать с функциями. Хитрость заключается в том, чтобы разделить печатную и непечатаемую части функции так, чтобы вы могли правильно заключить непечатаемые части в []. Обычно мне нравится, когда моя строка ERROR .. отделена (и это не проблема), но это также работает правильно, если все в одной строке.

Обратите внимание, что я возвращаю предыдущие $? значение от каждого суб-оболочки так $? распространяется от одного к другому.

PS1="\n\
\[\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \$E_ERROR;
  fi
  exit \$cja_prv_retval
\`\]\
\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \"ERROR: RETURN CODE \$cja_prv_retval\";
  fi
  exit \$cja_prv_retval
\`\
\[\`
  cja_prv_retval=\$?;
  if [ \$cja_prv_retval != 0 ];
     then echo -ne \$E_RESET;
  fi
  exit \$cja_prv_retval
\`\]\
${P_RESET}${P_GRAY}\! \t ${P_RED}\u${P_GRAY}@${P_GREEN}\h ${P_YELLOW}\w ${P_CYAN}   ══>${P_RESET} "

Это дает мне либо

2021 12:28:05 [email protected] ~ ══>

если нет ошибки, или

ERROR: RETURN CODE 1 2021 12:28:16 [email protected] ~ ══>

если есть ошибка. Все правильно расположено (редактирование многострочной истории работает правильно).

0
ChrisAshton84