Строка, созданная с помощью tput, удаляется при прокрутке

У меня есть следующая функция BASH, которая принимает аргументы и отображает их в нижней части терминала в новой строке, которая исключена из области прокрутки:

bottomLine() {
    clear
    # Get all arguments and assign them to a var
    CONTENT=$@
    # Save cursor position
    tput sc
    # Add a new line
    tput il 1
    # Change scroll region to exclude the last lines
    tput csr 0 $(($(tput lines) - 3))
    # Move cursor to bottom line
    tput cup $(tput lines) 0
    # Clear to the end of the line
    tput el
    # Echo the content on that row
    echo -ne "${CONTENT}"
    # Restore cursor position
    tput rc
}

Это довольно просто и работает. Дело в том, что после некоторых команд (иногда после нескольких, иногда после 15 минут работы) строка прокручивается вверх, даже если она должна быть исключена из области прокрутки.

Это происходит со мной как в Тильде, так и в Терминаторе.

Любая помощь будет оценена, ура.

РЕДАКТИРОВАТЬ: лучший способ воспроизвести проблему, если вы выполните несколько "ls -a, ls -a, ls -a, ls -a", пока не достигнете нижней части страницы, затем откройте случайный файл с помощью Vi и затем выполните другой "лс -а". Когда вы делаете это, нижний ряд с прокруткой поднимается выше, даже если это не так.

1 ответ

Решение

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

Я изменил вашу функцию, чтобы она автоматически обновляла подсказку при первом вызове. Для этого мне пришлось разделить его на две функции.

bottomLineTermCtlSeq() {
    #clear
    # Save cursor position
    tput sc
    # Add a new line
    tput il 1
    # Change scroll region to exclude the last lines
    tput csr 0 $(($(tput lines) - 3))
    # Move cursor to bottom line
    tput cup $(tput lines) 0
    # Clear to the end of the line
    tput el
    # Echo the content on that row
    cat "${BOTTOM_LINE_CONTENT_FILE}"
    # Restore cursor position
    tput rc
}

bottomLine() {
    local bottomLinePromptSeq='\[$(bottomLineTermCtlSeq)\]'
    if [[ "$PS1" != *$bottomLinePromptSeq* ]]
    then
        PS1="$bottomLinePromptSeq$PS1"
    fi
    if [ -z "$BOTTOM_LINE_CONTENT_FILE" ]
    then
        export BOTTOM_LINE_CONTENT_FILE="$(mktemp --tmpdir bottom_line.$$.XXX)"
    fi
    echo -ne "$@" > "$BOTTOM_LINE_CONTENT_FILE"
    bottomLineTermCtlSeq
}

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

Обратите внимание, что я удалил clear команда из последовательности манипулирования терминалом, что означает, что вам может потребоваться вызвать ее самостоятельно перед вызовом bottomLine в первый раз (когда вы звоните, когда достигли нижней части экрана).

Также обратите внимание, что нижняя строка может быть испорчена при изменении размера окна терминала.

Другие вопросы по тегам