3

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

4

1 回答 1

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
}

我将底线的当前内容存储在文件中而不是环境变量中,以便顶级外壳的子进程也可以操作底线。

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

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

于 2018-08-17T15:19:56.913 回答