Tui
Nvim :help
pages, generated
from source
using the tree-sitter-vimdoc parser.
By default when you run
nvim
(without
--embed or
--headless) it starts
the builtin "terminal UI" (TUI). This default UI is optional: you can run Nvim
as a "headless" server, or you can use a
GUI.
Nvim has a client-server architecture: by default when you run
nvim
, this
starts the builtin UI client, which starts a
nvim --embed
server (child)
process that the UI client connects to. After attaching to the server, the UI
client calls
nvim_set_client_info() (as recommended for all UIs
dev-ui)
and sets these fields on its channel:
client = {
attributes = {
license = 'Apache 2',
pid = …,
website = 'https://neovim.io',
},
name = 'nvim-tui',
type = 'ui',
version = { … },
}
Nvim guesses the terminal type when it starts (except in
--embed and
--headless modes). The
$TERM environment variable is the primary hint that
determines the terminal type.
terminfo E557 E558 E559
To display its user interface, Nvim reads a list of "terminal capabilities"
from the system terminfo database (or builtin defaults if terminfo is not
found). If that information is wrong, the screen may be messed up or keys may
not be recognized.
The Unibilium library (used to read terminfo) allows you to override the
system terminfo with one in the "$HOME/.terminfo/" directory. Building your
own terminfo is usually as simple as running this:
curl -LO https://invisible-island.net/datafiles/current/terminfo.src.gz
gunzip terminfo.src.gz
tic -x terminfo.src
$TERM
The $TERM environment variable must match the terminal you are using!
Otherwise Nvim cannot know what sequences your terminal expects, and weird
or sub-optimal behavior will result (scrolling quirks, wrong colors, etc.).
$TERM is also important because it is forwarded by SSH to the remote session,
unlike most other environment variables.
For this terminal Set $TERM to |builtin-terms|
-------------------------------------------------------------------------
anything libvte-based vte, vte-256color Y
(e.g. GNOME Terminal) (aliases: gnome, gnome-256color)
iTerm (original) iterm, iTerm.app N
iTerm2 (new capabilities) iterm2, iTerm2.app Y
Konsole konsole-256color N
Linux virtual terminal linux, linux-256color Y
PuTTY putty, putty-256color Y
rxvt rxvt, rxvt-256color Y
screen screen, screen-256color Y
simple terminal (st) st, st-256color Y
Terminal.app nsterm N
tmux tmux, tmux-256color Y
Windows/ConEmu conemu Y
Windows/Cygwin-built Nvim cygwin Y
Windows/Interix interix Y
Windows/VTP console vtpcon Y
Windows/legacy console win32con Y
xterm or compatible xterm, xterm-256color Y
builtin-terms builtin_terms
If a
terminfo database is not available or there is no entry for the current
terminal, Nvim will map
$TERM to a builtin entry according to the above
table, or "ansi" if there is no match. For example "TERM=putty-256color" will
be mapped to the builtin "putty" entry. See also
tui-colors.
The builtin terminfo is not combined with any external terminfo database, nor
can it be used in preference to one. You can thus entirely override any
omissions or out-of-date information in the builtin terminfo database by
supplying an external one with entries for the terminal type.
If you want to set terminal-dependent options or mappings, you can do this in
your init.vim. Example:
if $TERM =~ '^\(rxvt\|screen\|interix\|putty\)\(-.*\)\?$'
set notermguicolors
elseif $TERM =~ '^\(tmux\|iterm\|vte\|gnome\)\(-.*\)\?$'
set termguicolors
elseif $TERM =~ '^\(xterm\)\(-.*\)\?$'
if $XTERM_VERSION != ''
set termguicolors
elseif $KONSOLE_PROFILE_NAME != ''
set termguicolors
elseif $VTE_VERSION != ''
set termguicolors
else
set notermguicolors
endif
elseif $TERM =~ ...
... and so forth ...
endif
scroll-region xterm-scroll-region
Where possible, Nvim will use the terminal's ability to set a scroll region in
order to redraw faster when a window is scrolled. If the terminal's terminfo
description describes an ability to set top and bottom scroll margins, that is
used.
This will not speed up scrolling in a window that is not the full width of the
terminal. Xterm has an extra ability, not described by terminfo, to set left
and right scroll margins as well. If Nvim detects that the terminal is Xterm,
it will make use of this ability to speed up scrolling that is not the full
width of the terminal.
tui-input
Historically, terminal emulators could not distinguish between certain control
key modifiers and other keys. For example,
<C-I>
and
<Tab>
are represented in
the same way, as are
<Esc>
and
<C-[>
,
<CR>
and
<C-M>
, and
<NL>
and
<C-J>
.
Modern terminal emulators are able to distinguish between these pairs of keys
by encoding control modifiers differently. There are two common but distinct
ways of doing this, known as "modifyOtherKeys" and "CSI u". Nvim supports both
encoding methods and at startup will tell the terminal emulator that it
understands these key encodings. If your terminal emulator supports it then
this will allow you to map the key pairs listed above separately.
<Tab>
Nvim uses libtermkey to convert terminal escape sequences to key codes.
terminfo is used first, and CSI sequences not in
terminfo (including
extended keys a.k.a. "modifyOtherKeys" or "CSI u") can also be parsed.
For example, when running Nvim in tmux, this makes Nvim leave Insert mode and
go to the window below:
tmux send-keys 'Escape' [ 2 7 u 'C-W' j
Where
'Escape' [ 2 7 u
is an unambiguous "CSI u" sequence for the
<Esc>
key.
The kitty keyboard protocol
https://sw.kovidgoyal.net/kitty/keyboard-protocol/
is partially supported, including keypad keys in Unicode Private Use Area.
For example, this sequence is recognized by Nvim as
<C-kEnter>
:
CSI 57414 ; 5 u
and can be used differently from
<C-CR>
in mappings.
tui-modifyOtherKeys tui-csiu
At startup Nvim will query your terminal to see if it supports the "CSI u"
encoding by writing the sequence
CSI ? u CSI c
If your terminal emulator responds with
CSI ? <flags> u
this means your terminal supports the "CSI u" encoding and Nvim will tell your
terminal to enable it by writing the sequence
CSI > 1 u
If your terminal does not support "CSI u" then Nvim will instead enable the
"modifyOtherKeys" encoding by writing the sequence
CSI > 4 ; 2 m
When Nvim exits cleanly it will send the corresponding sequence to disable the
special key encoding. If Nvim does not exit cleanly then your terminal
emulator could be in a bad state. If this happens, simply run "reset".
tui-colors
Nvim uses 256 colours by default, ignoring
terminfo for most terminal types,
including "linux" (whose virtual terminals have had 256-colour support since
4.8) and anything claiming to be "xterm". Also when $COLORTERM or $TERM
contain the string "256".
Nvim similarly assumes that any terminal emulator that sets $COLORTERM to any
value, is capable of at least 16-colour operation.
It uses the "setrgbf" and "setrgbb"
terminfo extensions (proposed by Rüdiger
Sonderfeld in 2013). If your terminfo definition is missing them, then Nvim
will decide whether to add them to your terminfo definition, using the ISO
8613-6:1994/ITU T.416:1993 control sequences for setting RGB colours (but
modified to use semicolons instead of colons unless the terminal is known to
follow the standard).
Another convention, pioneered in 2016 by tmux, is the "Tc" terminfo extension.
If terminfo has this flag, Nvim will add constructed "setrgbf" and "setrgbb"
capabilities as if they had been in the terminfo definition.
If terminfo does not (yet) have this flag, Nvim will fall back to $TERM and
other environment variables. It will add constructed "setrgbf" and "setrgbb"
capabilities in the case of the "rxvt", "linux", "st", "tmux", and "iterm"
terminal types, or when Konsole, genuine Xterm, a libvte terminal emulator
version 0.36 or later, or a terminal emulator that sets the COLORTERM
environment variable to "truecolor" is detected.
xterm-resize
Nvim can resize the terminal display on some terminals that implement an
extension pioneered by dtterm.
terminfo does not have a flag for this
extension. So Nvim simply assumes that (all) "dtterm", "xterm", "teraterm",
"rxvt" terminal types, and Konsole, are capable of this.
tui-cursor-shape
Nvim will adjust the shape of the cursor from a block to a line when in insert
mode (or as specified by the
'guicursor' option), on terminals that support
it. It uses the same
terminfo extensions that were pioneered by tmux for
this: "Ss" and "Se".
Similarly, if you set the cursor highlight group with blend=100, Nvim hides
the cursor through the "cvvis" and "civis" extensions.
If your terminfo definition is missing them, then Nvim will decide whether to
add them to your terminfo definition, by looking at $TERM and other
environment variables. For the "rxvt", "putty", "linux", "screen",
"teraterm", and "iterm" terminal types, or when Konsole, a libvte-based
terminal emulator, or genuine Xterm are detected, it will add constructed
"Ss" and "Se" capabilities.
tui-cursor-tmux
Within tmux it may appear that Nvim is not changing the cursor, but in fact it
is tmux receiving instructions from Nvim to change the cursor and not knowing
what to do in turn. tmux must translate what it receives from Nvim into
whatever control sequence is appropriate for the host terminal. It shares
a common mechanism with Nvim, of using the "Ss" and "Se" capabilities from
terminfo (for the output terminal) if they are present. Unlike Nvim, if they
are not in terminfo you must add them by setting "terminal-overrides" in
~/.tmux.conf .
See the tmux(1) manual page for the details of how and what to do in the tmux
configuration file. It will look something like:
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
or (alas!) for Konsole 18.07.70 or older, something more complex like:
set -ga terminal-overrides 'xterm*:\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%{1}%;%d\007'
[This is about the size of the whole window Vim is using, not a window that is
created with the ":split" command.]
On Unix systems, three methods are tried to get the window size:
an ioctl call (TIOCGSIZE or TIOCGWINSZ, depends on your system)
the environment variables "LINES" and "COLUMNS"
from the
terminfo entries "lines" and "columns"
If everything fails a default size of 24 lines and 80 columns is assumed. If
a window-resize signal is received the size will be set again. If the window
size is wrong you can use the
'lines' and
'columns' options to set the
correct values. See
:mode.
If you have a slow terminal you may want to reset the
'showcmd' and
'ruler'
options. The command characters and cursor positions will not be shown in the
status line (which involves a lot of cursor motions and attribute changes for
every keypress or movement). If the terminal scrolls very slowly, set the
'scrolljump' to 5 or so. If the cursor is moved off the screen (e.g., with
"j") Vim will scroll 5 lines at a time. Another possibility is to reduce the
number of lines that Vim uses with the command "z{height}<CR>".
If the characters from the terminal are arriving with more than 1 second
between them you might want to set the
'timeout' and/or
'ttimeout' option.
If you are using a color terminal that is slow when displaying lines beyond
the end of a buffer, this is because Nvim is drawing the whitespace twice, in
two sets of colours and attributes. To prevent this, use this command:
hi NonText cterm=NONE ctermfg=NONE
This draws the spaces with the default colours and attributes, which allows the
second pass of drawing to be optimized away.
Note: Although in theory the
colours of whitespace are immaterial, in practice they change the colours of
cursors and selections that cross them. This may have a visible, but minor,
effect on some UIs.
<S-LeftMouse> <A-RightMouse> <S-RightMouse> <RightDrag>
<RightRelease> <LeftDrag>
Normal Mode:
event position selection change action
cursor window
---------------------------------------------------------------------------
<LeftMouse> yes end yes
<C-LeftMouse> yes end yes "CTRL-]" (2)
<S-LeftMouse> yes no change yes "*" (2)
<LeftDrag> yes start or extend (1) no
<LeftRelease> yes start or extend (1) no
<MiddleMouse> yes if not active no put
<MiddleMouse> yes if active no yank and put
<RightMouse> yes start or extend yes
<A-RightMouse> yes start or extend blockw. yes
<S-RightMouse> yes no change yes "#" (2)
<C-RightMouse> no no change no "CTRL-T"
<RightDrag> yes extend no
<RightRelease> yes extend no
Insert or Replace Mode:
event position selection change action
cursor window
---------------------------------------------------------------------------
<LeftMouse> yes (cannot be active) yes
<C-LeftMouse> yes (cannot be active) yes "CTRL-O^]" (2)
<S-LeftMouse> yes (cannot be active) yes "CTRL-O*" (2)
<LeftDrag> yes start or extend (1) no like CTRL-O (1)
<LeftRelease> yes start or extend (1) no like CTRL-O (1)
<MiddleMouse> no (cannot be active) no put register
<RightMouse> yes start or extend yes like CTRL-O
<A-RightMouse> yes start or extend blockw. yes
<S-RightMouse> yes (cannot be active) yes "CTRL-O#" (2)
<C-RightMouse> no (cannot be active) no "CTRL-O CTRL-T"
In a help window:
event position selection change action
cursor window
---------------------------------------------------------------------------
<2-LeftMouse> yes (cannot be active) no "^]" (jump to help tag)
When
'mousemodel' is "popup", these are different:
<A-LeftMouse>
Normal Mode:
event position selection change action
cursor window
---------------------------------------------------------------------------
<S-LeftMouse> yes start or extend (1) no
<A-LeftMouse> yes start/extend blockw no
<RightMouse> no popup menu no
Insert or Replace Mode:
event position selection change action
cursor window
---------------------------------------------------------------------------
<S-LeftMouse> yes start or extend (1) no like CTRL-O (1)
<A-LeftMouse> yes start/extend blockw no
<RightMouse> no popup menu no
(1) only if mouse pointer moved since press
(2) only if click is in same buffer
Clicking the left mouse button causes the cursor to be positioned. If the
click is in another window that window is made the active window. When
editing the command-line the cursor can only be positioned on the
command-line. When in Insert mode Vim remains in Insert mode. If
'scrolloff'
is set, and the cursor is positioned within
'scrolloff' lines from the window
border, the text is scrolled.
A selection can be started by pressing the left mouse button on the first
character, moving the mouse to the last character, then releasing the mouse
button. You will not always see the selection until you release the button,
only in some versions (GUI, Win32) will the dragging be shown immediately.
Note that you can make the text scroll by moving the mouse at least one
character in the first/last line in the window when
'scrolloff' is non-zero.
In Normal, Visual and Select mode clicking the right mouse button causes the
Visual area to be extended. When
'mousemodel' is "popup", the left button has
to be used while keeping the shift key pressed. When clicking in a window
which is editing another buffer, the Visual or Select mode is stopped.
In Normal, Visual and Select mode clicking the right mouse button with the alt
key pressed causes the Visual area to become blockwise. When
'mousemodel' is
"popup" the left button has to be used with the alt key. Note that this won't
work on systems where the window manager consumes the mouse events when the
alt key is pressed (it may move the window).
double-click <2-LeftMouse> <3-LeftMouse> <4-LeftMouse>
Double, triple and quadruple clicks are supported when the GUI is active, for
Win32 and for an xterm. For selecting text, extra clicks extend the
selection:
click select
---------------------------------
double word or % match
triple line
quadruple rectangular block
Exception: In a Help window a double click jumps to help for the word that is
clicked on.
A double click on a word selects that word.
'iskeyword' is used to specify
which characters are included in a word. A double click on a character
that has a match selects until that match (like using "v%"). If the match is
an #if/#else/#endif block, the selection becomes linewise.
For MS-Windows and xterm the time for double clicking can be set with the
'mousetime' option. For the other systems this time is defined outside of Vim.
An example, for using a double click to jump to the tag under the cursor:
:map <2-LeftMouse> :exe "tag " .. expand("<cword>")<CR>
Dragging the mouse with a double click (button-down, button-up, button-down
and then drag) will result in whole words to be selected. This continues
until the button is released, at which point the selection is per character
again.
In Insert mode, when a selection is started, Vim goes into Normal mode
temporarily. When Visual or Select mode ends, it returns to Insert mode.
This is like using
CTRL-O
in Insert mode. Select mode is used when the
'selectmode' option contains "mouse".
X1Mouse X1Drag X1Release
X2Mouse X2Drag X2Release
<MiddleRelease> <MiddleDrag>
Mouse clicks can be mapped. The codes for mouse clicks are:
code mouse button normal action
---------------------------------------------------------------------------
<LeftMouse> left pressed set cursor position
<LeftDrag> left moved while pressed extend selection
<LeftRelease> left released set selection end
<MiddleMouse> middle pressed paste text at cursor position
<MiddleDrag> middle moved while pressed -
<MiddleRelease> middle released -
<RightMouse> right pressed extend selection
<RightDrag> right moved while pressed extend selection
<RightRelease> right released set selection end
<X1Mouse> X1 button pressed -
<X1Drag> X1 moved while pressed -
<X1Release> X1 button release -
<X2Mouse> X2 button pressed -
<X2Drag> X2 moved while pressed -
<X2Release> X2 button release -
The X1 and X2 buttons refer to the extra buttons found on some mice. The
'Microsoft Explorer' mouse has these buttons available to the right thumb.
Currently X1 and X2 only work on Win32 and X11 environments.
Examples:
:noremap <MiddleMouse> <LeftMouse><MiddleMouse>
Paste at the position of the middle mouse button click (otherwise the paste
would be done at the cursor position).
:noremap <LeftRelease> <LeftRelease>y
Immediately yank the selection, when using Visual mode.
Note the use of ":noremap" instead of "map" to avoid a recursive mapping.
:map <X1Mouse> <C-O>
:map <X2Mouse> <C-I>
Map the X1 and X2 buttons to go forwards and backwards in the jump list, see
CTRL-O and
CTRL-I.
mouse-swap-buttons
To swap the meaning of the left and right mouse buttons:
:noremap <LeftMouse> <RightMouse>
:noremap <LeftDrag> <RightDrag>
:noremap <LeftRelease> <RightRelease>
:noremap <RightMouse> <LeftMouse>
:noremap <RightDrag> <LeftDrag>
:noremap <RightRelease> <LeftRelease>
:noremap g<LeftMouse> <C-RightMouse>
:noremap g<RightMouse> <C-LeftMouse>
:noremap! <LeftMouse> <RightMouse>
:noremap! <LeftDrag> <RightDrag>
:noremap! <LeftRelease> <RightRelease>
:noremap! <RightMouse> <LeftMouse>
:noremap! <RightDrag> <LeftDrag>
:noremap! <RightRelease> <LeftRelease>