I have the following BASH function that takes arguments and displays them at the bottom of the terminal in a new line that's excluded from the scroll region:
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
}
It's fairly straightforward and works. Thing is, after some commands (sometimes after just a few, sometimes after 15 minutes of work) the line would get scrolled up even though it should be excluded from the scrolling region.
This happens to me in both Tilda and Terminator.
Any help would be appreciated, cheers.
EDIT: The best way to reproduce the issue is if you do several "ls -a, ls -a, ls -a, ls -a" until you reach the bottom of the page, then open a random file with Vi and then do another "ls -a". When you do this, the unscrollable bottom row goes above even though it shouldn't.
My first impulse was to answer that there is no way to freeze the scrollable region once and forever, since any program manipulating the terminal (like vim does) can override your settings. However then I figured out that you can restore the settings through the shell prompting functionality. To this end you must add your terminal control sequence to the PS1
environment variable.
I've modified your function so that it automatically updates the prompt the first time it is called. To this end I had to split it into two functions.
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
}
I store the current content of the bottom line in a file rather than in an environment variable so that subprocesses of the top level shell can also manipulate the bottom line.
Note that I removed the clear
command from the terminal manipulation sequence, which means that you may need to call it yourself before calling bottomLine
for the first time (when you call it while having reached to the bottom of your screen).
Also note that the bottom line can be messed up when the terminal window is resized.