How is it that VIM (when running) can display the contents of a file to the terminal, then (when closed) can take what was displayed back? There have been several applications I have made where I would have liked to implement this functionality... like when making a program with terminal graphics where the entire screen typically has to be updated when a single "object" moves.
It's your terminal that stores the old buffer, not Vim.
If you use XTerm emulation, Vim switches to the "alternate" terminal screen on startup. On exit, Vim switches back to the normal screen.
Terminfo strings at startup:
\E7 saves the cursor's position
\E[?47h switches to the alternate screen
Terminfo strings at exit:
\E[2J clears the screen (assumed to be the alternate screen)
\E[?47l switches back to the normal screen
\E8 restores the cursor's position.
Related
Here i found a link to this script which saves the screen size and position when exiting vim. If i use :mksession ~/session.vim in fullscreen mode with several splits, exit vim (gvim) and open it like: gvim -S ~/session.vim it messes up the sizes of the splits (pretty randomly. All splits have different sizes). They are all shifted to the left. Is there already a way of doing this properly?
Have you verified your 'sessionoptions'? It should include 'resize' and 'winsize' at the very least to get what you're looking for. :help 'ssop' will give you the list of options to set for what gets saved into session files.
When you enter vim, it "clears" the screen. Upon exiting, it "restores" the original contents.
I understand one can use \x1b[2J to clear the console and reset the cursor position, but this will overwrite terminal contents.
I assume Vim uses ncurses under the hood, in which case I suppose the better question is how ncurses does this, but how is it done?
Regarding the answer by #Keith Thompson — not exactly:
vim does not use the screen optimization of ncurses which sends smcup and rmcup automatically. Rather, it is a termcap application. It follows a convention used by most (not all) termcap applications. There are some implementations of vi which do not for instance (on IRIX64 perhaps).
as for "most terminals" — actually, xterm look-alikes are a small part of the terminal database (even counting variations, less than 10%). Rephrase that to something like "the most common terminal emulators on Linux.
the terminal does not save and restore the screen contents. Instead, it switches between two screens (in xterm's documentation "normal" and "alternate"). In xterm for instance, one can always switch between the two using a menu entry. The xterm FAQ Why doesn't the screen clear when running vi? gives more detail.
for better context, note that smcup is an (obscure) abbreviation for set-mode-cursor-positioning, or start cursor-positioning mode. (also cursor-addressing). The r in rmcup means "reset" (and m means "mode"). set/reset have different connotations from save/restore; with the latter the user is led to believe that the values can be stacked up.
Most terminal emulators are able to save and restore the contents of the screen.
The terminfo codes for this are smcup to enter full-screen mode and rmcup to leave it. (The older termcap codes are ti and te.)
If these capabilities are enabled in the terminfo database, any program that uses ncurses will print the smcup string on entry, and the rmcup string on exit.
On the system I'm using at the moment, the strings are (with \E representing the Escape character):
smcup: \E7\E[?1;47h
rmcup: \E[2J\E[?1;47l\E8
This restores the previous contents of the screen as well as the cursor position.
The specific meanings of the sequences (for xterm) are documented here:
smcup:
\E7 Save Cursor
\E[?1;47h Application Cursor Keys; Use Alternate Screen Buffer
rmcup:
\E[2J Erase screen
\E[?1;47l Application Cursor Keys; Use Normal Screen Buffer
\E8 Restore Cursor
(This assumes I'm understanding the use of the semicolon correctly; I'm not 100% sure of that.)
When I enter a shell command via vim -- e.g., :!rake routes -- I'll get some output and then:
Press ENTER or type command to continue
If I press anything at that point, I am always taken back to the main vim UI. How do I stay in that shell mode for a bit longer, specifically I can scroll back to see all the output of the command?
For terminal vim scrolling is provided by terminal emulator (or terminal multiplexer like tmux/screen if you use it). I.e. if your terminal scrolls when using <S-PageUp> it must also scroll with Vim’s !. Same for mouse wheel (it works for me even if vim was configured to handle mouse on its own).
If have terminal vim and you need to view output after you pressed <CR> then you can use <C-z>/:susp. Both these capabilities will be spoiled with incorrect configuration of either vim or terminal (terminal multiplexer) (i.e. terminal configured not to support alternate screens (which is normally issue for terminal multiplexers rather then terminal emulators: screen requires altscreen on in .screenrc) or vim setting telling vim what to output to the terminal on startup/resume and shutdown/suspend was spoiled).
If you have GUI vim your options are very limited. It is better to follow link provided by #glts or #EricAndres advice in this case as I do not use GUI vim.
:r! [shell command] will read the output from the command into the buffer. So if you open a new buffer then use that command, you can search and scroll through it all you like. See Vimcasts episode 57 for more information.
I'm trying to wrap my head around VT102 sequences and how such libraries as ncurses work.
To give an example, when I open Emacs, it fills the terminal window. When I hit C-x C-c, the program exits and my terminal window looks exactly as it looked before I launched emacs (i.e. the line above my cursor shows the emacs command in my zsh history, not whatever emacs had rendered).
As a sort of "hello world", I've written a little ruby script that opens /dev/tty, then writes \x1B[48;597m\n (blank lines, with a background color) for as many rows as there are in my terminal. The program then sleeps for 5 seconds, leaving me happily staring at a bright orange screen momentarily. Then it exits, leaving me at my zsh prompt, with 53 lines of bright orange up above it.
Two questions:
Is writing blank lines with a background color the correct way to fill the terminal window with color?
How do I completely clear the screen by sending some VT102 sequence to /dev/tty?
I am able to send \x1B[2J, but this does the same thing as when I execute the clear command, and actual just shifts all the content up the terminal window, until my cursor is at the very top of a blank window, rather than leaving my cursor wherever it would naturally be if my program had not written a load of blank lines to the screen.
PS: Not sure what tags to use here that anybody is actually likely to be subscribed to.
Is writing blank lines with a background color the correct way to fill the terminal window with color?
No. The correct way to do this (on a terminal that supports BCE*) is to set a background color, then erase the screen using an ED sequence (e.g, ^[ [ 2 J).
*: most modern terminals do
How do I completely clear the screen by sending some VT102 sequence to /dev/tty?
Using ED. See above.
If what you actually want to do is switch to the alternate screen (like emacs is doing in your example), the alternate screen is controlled by private mode 1049. You can switch to it using ^[ [ ? 1 0 4 9 h, and switch back using ^[ [ ? 1 0 4 9 l. Note, however, that this is an xterm extension; it's not entirely standard, and wasn't supported by any DEC hardware terminals (e.g, the VT102).
I want to see the original contents of screen after quitting vim
as they were before opening a file , as of not my file quits but the original display is not there
THanks
The feature of returning screen contents after running a full screen application vs, leaving the contents there, is not specific to vi, but to your terminal emulator. The feature you want to turn on to return to the previous text is often known as 'altscreen'. If you are using xterm as your terminal emulator, this behaviour is default. However if you are running GNU Screen inside of an xterm (or other terminal), you need to add the line
altscreen on
to your ~/.screenrc file. Other terminals that support this feature will have other mechanisms to turn it on and off.
Instead of quitting, you can put vim into the background by typing control-z. This restores the previous screen, but leaves you the editor running 'stopped' with the current file. To get vim back, enter the command
fg %1 at the shell prompt. This brings vim back to the foreground again - at least assuming you only have one stopped job. The command jobs will give you a list of stopped jobs, which you can access by number.
So the work sequence becomes edit, save, control-z, compile, test, fg...
This works on linux, and Mac OS X - YMMV on other Unix variants.
If you are using xterm, then see :help xterm-screens, or ... read that anyway as it describes that your problem should be related to some terminfo setting - probably.
HTH