Ответ 1
Небольшой трюк с использованием PROMPT_COMMAND
:
Значение переменной
PROMPT_COMMAND
проверяется непосредственно перед тем, как Bash печатает каждое основное приглашение. ЕслиPROMPT_COMMAND
установлено и имеет ненулевое значение, тогда значение выполняется так же, как если бы оно было введено в командной строке.
Следовательно, если вы поместите это в свой .bashrc
:
_my_prompt_command() {
local curpos
echo -en "\E[6n"
IFS=";" read -sdR -a curpos
((curpos[1]!=1)) && echo -e '\E[1m\E[41m\E[33m%\E[0m'
}
PROMPT_COMMAND=_my_prompt_command
ты будешь очень хорош. Не стесняйтесь использовать другие причудливые цвета в части echo "%"
. Вы можете даже поместить содержимое этого в переменную, чтобы вы могли изменять его на лету.
Трюк: получите столбец курсора (с echo -en "\E[6n"
, за которым следует команда read
), прежде чем распечатать приглашение, а если оно не 1, напечатайте %
и новую строку.
Плюсы:
- чистый Bash (без внешних команд),
- нет подоболочек,
- оставляет ваш
PS1
все приятным и чистым: если вы иногда меняете свойPS1
(я делаю это, когда работаю в глубоко вложенном каталоге - мне не нравятся подсказки, которые выполняются на нескольких милях), это будет работать.
В качестве тройных комментариев вы можете использовать stty
вместо эхо-сигнала с жестко запрограммированной управляющей последовательностью. Но это использует внешнюю команду и не является чистым Bash. Адаптируйте к вашим потребностям.
Что касается вашей проблемы с уродливыми кодами символов, которые получают случайную печать: это может быть потому, что в буфере tty все еще есть вещи. Может быть несколько исправлений:
-
Выключите, а затем
echo
терминала, используяstty
.set_prompt() { local curpos stty -echo echo -en '\033[6n' IFS=';' read -d R -a curpos stty echo (( curpos[1] > 1 )) && echo -e '\033[7m%\033[0m' } PROMPT_COMMAND=set_prompt
Основное отличие состоит в том, что комбо
echo
/read
было обернуто с помощьюstty -echo
/stty echo
, которое соответственно отключает и разрешает эхо-сигнал на терминале (что почему опция-s
дляread
теперь бесполезный). В этом случае вы не получите правильную позицию курсора, и это может привести к появлению странных сообщений об ошибках или%
не будет выводиться вообще. -
Явно очистить буфер tty:
set_prompt() { local curpos while read -t 0; do :; done echo -en '\033[6n' IFS=';' read -s -d R -a curpos (( curpos[1] > 1 )) && echo -e '\033[7m%\033[0m' } PROMPT_COMMAND=set_prompt
-
Просто сдайте, если буфер tty не может быть очищен:
set_prompt() { local curpos if ! read -t 0; then echo -en '\033[6n' IFS=';' read -s -d R -a curpos (( curpos[1] > 1 )) && echo -e '\033[7m%\033[0m' # else # here there was still stuff in the tty buffer, so I couldn't query the cursor position fi } PROMPT_COMMAND=set_prompt
В качестве примечания: вместо read
ing в массиве curpos
вы можете напрямую получить положение курсора в переменных, например curx
и cury
, как показано ниже:
IFS='[;' read -d R _ curx cury
Если вам нужна только позиция y cury
:
IFS='[;' read -d R _ _ cury