I'm running Centos7 with TERM=linux. Whenever I open a file with vi, or vim, the previous 30 lines in my bash window are over written. vi works fine, but when scrolling back, those 30 lines are lost forever. I have never seen this behavior with vi on Mac OS, Solaris or Oracle Linux. Any idea how to prevent this?
Restoring the terminal content requires the term codes
t_te. Vim determines this codes from the termcap definitions (or is is termlib?). It seems that those term codes are not available for
Test it by executing
:set t_ti? t_te?
This will show that the two codes are not set.
It might work, if you put the following into your
set t_ti=^[7^[[r^[[?47h t_te=^[[?47l^[8
^[ is the escape character, type
<C-v><esc> to insert it.
This is mentioned in the
:h restorescreen (a Windows-only option).
BTW: Once Vim is running, it is the master of the terminal. So scrollback is only possible after you left Vim. And
vi is also a Vim. Check with
:version while inside Vi.
You've unwittingly become used to the semantics of paper terminals rather than video terminals.
On an old paper terminal, there was a Form Feed control character which caused the (usually continuous, fan-fold) paper to roll up to the start of the next sheet/form, and old lines would be on a long trail of paper hanging off the back of the terminal.
On video terminals from the 1960s, 1970s, and 1980s, there was a fixed size screen that could be erased, alongside explicitly moving the cursor back to the home position. (Usually the Form Feed control character did not do this. It would just act like a newline, and there would be a different Erase Display control sequence for erasing the screen. Video terminals were not like some contemporary home computers'
PRINT CHR$(12) in this respect.)
Terminal emulators mainly followed the semantics of video terminals. (Indeed, the world went through a phase of video terminals often actually being IBM PC compatible machines running terminal emulation programs, rather than dedicated machines.) But the (mainly) GUI ones that run on Unices and Linux-based operating systems have gained stuff over the years, including two important mechanisms here that video terminals did not have: the scrollback buffer and the alternative display buffer.
On an old video terminal, a full screen program like
vi or VIM would indeed erase the screen in order to display its full screen user interface, and the behaviour that you witnessed would be the quite normal behaviour.
On terminal emulators with alternative screen buffers
vi et al. are actually being fooled into switching to the alternative screen buffer instead, which they erase and switch back from when they are done.
They don't actually think that they are switching to an alternative screen buffer; they think that they are "entering cursor addressing mode". This is an idea invented by termcap/terminfo that video terminals have a normal "line by line" mode where cursor movement control sequences do not wholly work, and that there's a "cursor addressing mode" that needs to be switched into for a full-screen program to be able to move the cursor around the whole screen. For most types of modern terminal, for the supposed "cursor addressing mode" termcap/terminfo in reality provides the control sequences for switching to and from the alternative screen buffer.
So, for your first mismatched expectation, with your
TERM environment variable set to
linux terminfo's idea of "cursor addressing mode" does not include switching to the alternative screen buffer.
This is because the terminal emulator built into Linux, which is what the
linux terminal type denotes, does not have an alternative screen buffer mechanism.
So its termcap/terminfo record does not give the control sequences for one.
This brings up an important point: Your terminal type in the
TERM environment variable must match the actual terminal that your program is, locally or remotely, talking to. Clearly you are not using the Linux built-in terminal emulator, and you should not be using the
linux terminal type. Common MacOS terminal emulators correspond to the terminal types
iTerm.app and so forth. No, it should not be
The scrollback buffer is another change from the video terminal paradigm, that effectively reintroduces the old paper terminal semantics, of having sheets of scrolled-off stuff hanging off the top of the terminal. When the emulated video terminal scrolls, scrolled-off stuff is pushed into the scrollback buffer, and erasing the display (normally) only erases the part that is below the bottom of the scrollback buffer.
There are two things that give you difficulty here.
First, some GUI terminal emulators take the idea of going back to the old paper terminal semantics quite far. GNOME Terminal doesn't erase the screen like a video terminal at all, now. Ask it to Erase Display and it will perform a Form Feed instead, pushing everything into the scrollback buffer. (This is not a good idea, as it conflates Erase Display with Form Feed.) See "https://unix.stackexchange.com/q/375743/5132" for an example of the problems that that causes people. If you have become used to the GNOME Terminal way of doing things, be aware that these are the very old paper terminal semantics, not the (less old) video terminal ones.
Second, some other GUI terminal emulators think that the alternative screen buffer shouldn't be like the primary one, and actually do change the cursor addressing semantics a bit. Amusingly, what their implementors have most often chosen to do is not do scrolling, and as a logical consequence have no scrollback buffer, when the alternative screen buffer is active. (Sadly, this should really have been linked to the actual video terminal mechanism to emulate, which was the ability to turn "automatic right margin wrap" off and on with control sequences from the host, regardless of display buffer.)
This latter is what is causing you your further mismatched expectations.
vi or another full screen program is active on such a terminal emulator, there will not be scrollback available, because the full screen program has switched to the alternative screen buffer.
To retain scrollback, you can choose to fiddle with VIM (where this is controllable with
t_ti et al.) to tell it not to attempt entering cursor addressing mode, which means that the terminal emulator will not be switched to the alternative screen buffer.
But the tradeoff is that you do so at the expense of going back … erm … forward to the video terminal semantics of full screen programs erasing all of the primary display below the scrollback buffer.
- Jonathan de Boyne Pollard (2019). "TERM". Miscellany. nosh toolset.
I seem to have stumbled upon the solution to getting the "semantics of paper terminals" as @JdeBP calls it. Namely, add :set term=builtin_ansi to .vimrc
When this is done I can have TERM set to linux on both my Mac and Linux machines and everything works perfectly, including backspaces and arrow keys.
Incidentally, I also tried adding :set t_ti? t_te? to .vimrc, but not only did that not work, vi complained about the question marks.