0

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?

  • 3
    You probably don't want TERM=linux. What terminal emulator are you using? – Andy Dalton Jun 08 '20 at 01:31
  • @Andy Dalton The Centos7 is a google cloud VM which I am accessing via ssh from a from a Mac – Richard Gostanian Jun 08 '20 at 01:39
  • What is TERM set to in your mac terminal before you log into the remote host? You'll probably want to make it the same. – Andy Dalton Jun 08 '20 at 01:42
  • For me, that's TERM=xterm-256color – Andy Dalton Jun 08 '20 at 01:47
  • They were both set with TERM=linux. Now I've made them both xterm. This solved the original problem in that the previous 30 lines no longer disappear. It however resulted in a new, less severe, problem in that while in vi I cannot scroll up past the first line of the vi session. Once I exit vi, I can then scroll back as far as I want. – Richard Gostanian Jun 08 '20 at 02:43
  • 2
    @RichardGostanian So what's the question? Is it the original question as currently stated, or the new issue you mention in your latest comment? – Kusalananda Jun 08 '20 at 06:41

3 Answers3

3

Restoring the terminal content requires the term codes t_ti and t_te. Vim determines this codes from the termcap definitions (or is is termlib?). It seems that those term codes are not available for TERM=linux.

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 vimrc:

set t_ti=^[7^[[r^[[?47h t_te=^[[?47l^[8

IMPORTANT: ^[ 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.

Ralf
  • 507
  • 2
  • 10
3

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 xterm or xterm-256color.

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. When 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.

Further reading

  • Jonathan de Boyne Pollard (2019). "TERM". Miscellany. nosh toolset.
JdeBP
  • 68,745
0

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.

  • Wasn't the point that you're probably not supposed to use TERM=linux if you're not using that particular terminal? – Steven Lu Nov 15 '20 at 05:57