Bash 使用tput创建的行在滚动时被删除

Bash 使用tput创建的行在滚动时被删除,bash,tput,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 th

我有以下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”。当你这样做的时候,可滚动的最下面一行会在上面,即使它不应该在上面。

我的第一个冲动是回答说,没有办法永远冻结可滚动区域,因为任何操作终端的程序(如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
之前自己调用它(当您在到达屏幕底部时调用它)


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

可能您偶尔会在参数内传递换行符-请尝试
内容=$(tr-d'\n'@MarkSetchell抱歉,我试过了,但似乎不起作用。我在OP中添加了一个编辑,精确地解释了如何复制它。它在Terminator和Tilda中都是这样做的。太棒了。我就是这样做的,但我只是编辑了我的PS1,每次都会运行它,有一些破坏性的效果,但是你检查一下有什么可以使用的吗?谢谢!