使用tput创建的行在滚动条上被删除

时间:2018-07-04 14:23:08

标签: bash 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打开一个随机文件然后再执行另一个“ ls -a”。当您执行此操作时,即使无法滚动,最底端的行也会位于上方。

1 个答案:

答案 0 :(得分:2)

我的第一个冲动是回答说,无法永久冻结可滚动区域,因为任何操作终端的程序(如vim都可以)会覆盖您的设置。但是后来我发现可以通过shell提示功能恢复设置。为此,您必须将终端控制序列添加到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
}

我将底行的当前内容存储在文件中,而不是环境变量中,以便顶层shell的子进程也可以操纵底行。

请注意,我从终端操作序列中删除了clear命令,这意味着您可能需要在第一次调用bottomLine之前(在您到达屏幕底部)。

还请注意,调整终端窗口的大小时可能会弄乱底线。