使用 tput 创建的行在滚动时被删除
Line created with tput gets removed on scroll
我有以下 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
之前自己调用它(当您在有到达屏幕底部)。
另请注意,当终端 window 调整大小时,底线可能会被弄乱。
我有以下 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
之前自己调用它(当您在有到达屏幕底部)。
另请注意,当终端 window 调整大小时,底线可能会被弄乱。