Очистите старые строки подсказки в bash, чтобы сэкономить пространство прокрутки

11

Моя терминальная тема была такой,

терминал их раньше

Но я думал, что приглашение потратило столько времени. И позже мне пришла в голову мысль, что я могу очищать подсказку каждый раз, когда запускаю команду. Я использовал Bash, одним из решений является использование preexec_invoke_execфункции.

Я использую следующую команду для очистки последних символов приглашения:

echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"

Так что терминал очень чистый, вот так,

введите описание изображения здесь

Но теперь моя проблема в том, что возникнет проблема, если я захочу использовать несколько команд в одной строке , скажем, при использовании for i in ....

Вот полная версия функции в моем .bashrc,

preexec () { echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"; echo -n "$1"; echo -ne "  \033[37;2m["; echo -n "$2"; echo -ne "]\033[0m\n"; }
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`; 
    preexec "$this_command" "$this_pwd"
}
trap 'preexec_invoke_exec' DEBUG
Либин Вэнь
источник
Глиф Лефковиц зш трюк - приятно!
2
Простое решение начинается с zsh...
Жиль "ТАК - перестань быть злым"
Я пропустил ваш вопрос там ...
Дэвид Хоэлзер
@DavidHoelzer Хорошо, если вы делаете for i in $(seq 1 10); do ls; doneс его функцией, вывод итерационных команд, так сказать, «проглатывается». Таким образом, OP захотел обезопасить поведение, включив эту подсказку. Причина, по которой я поддерживаю это, - интерес к осведомленности в оболочке, удобство использования, обратная связь и переносимость. Ссылка, которую я поместил в своем предыдущем комментарии, ведет к сообщению о суперпользователе - они столкнулись с проблемой приписывания этого фрагмента, так что это прототип, который эмулирует встроенную функциональность zsh (что я считаю интересным) в форме функции прерывания Вот.

Ответы:

3

Сначала preexec_invoke_execнужно изменить, чтобы предотвратить многократное выполнение preexec. Также измените, preexecчтобы учесть фактическое количество строк в $PS1:

preexec () { 
    # delete old prompt; one "\e[1A\e[K" per line of $PS1
    for (( i=0, l=$(echo -e $PS1 | wc -l) ; i < l ; i++ ))
    do             
        echo -ne "\e[1A\e[K"
    done
    # replacement for prompt
    echo -ne "\e[31;1m$ \e[0m"
    echo -n "$1"
    echo -ne "  \e[37;2m["
    echo -n "$2"
    echo -e "]\e[0m"
}

preexec_invoke_exec () {
    [ -n "$DONTCLEANPROMPT" ] && return
    DONTCLEANPROMPT=x
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`
    preexec "$this_command" "$this_pwd"
}

trap 'preexec_invoke_exec' DEBUG

PROMPT_COMMAND='unset DONTCLEANPROMPT'

Для preexecповторного запуска DONTCLEANPROMPTдолжен быть либо не установлен, либо установлен на ''. Это делается с помощью команды PROMPT_COMMAND, которая запускается непосредственно перед выдачей основного приглашения. Поэтому preexecбудет выполняться один и только один раз для каждой командной строки.

Adaephon
источник
Ваше решение решает проблему с помощью forцикла! Спасибо! Есть еще одно неудобство. Что происходит, если вы выполняете lsкоманду и у вас есть вывод, а затем другой ls, вы увидите, что последняя строка предыдущего вывода стирается ... у вас есть идея, как решить эту проблему?
1
Вы, вероятно, используете подсказку с одной строкой. Измените первый эхо-сигнал prexecна печать "\033[1A\033[K\033[31;1m$ \033[0m", то есть только один \033[1A\033[K(переместите 1 строку вверх, удалите до конца строки) вместо двух.
Adaephon
Безупречный! Большое спасибо за ваше решение и нашли время, чтобы объяснить. Это решает проблему OP и отлаживает решение еще дальше. Делает это полезным для всех! Ура!