Skip to main content
ansicode

IL — Insert Line (CSI Pn L)

Open N blank lines at the cursor row and push subsequent lines down within the scrolling region — vim's 'O' command primitive.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x1b[PnL
\\033[\033[PnL
\\e[\e[PnL
ESC [ESC [ Pn L
hex1b 5b <Pn> 4c

Description

Insert Line. Final byte L (0x4c) inserts Pn blank lines at the cursor row (default 1); every subsequent line inside the active scrolling region (DECSTBM, default = full screen) is pushed downward by Pn, and the Pn lines that would fall below the bottom margin are discarded. Cells in the freshly-inserted blank lines carry the current SGR background. The cursor moves to column 1 of its row (ECMA-48 says column unchanged, but most modern terminals follow the xterm convention of resetting to column 1 because that's what every TUI app expects). Used by vim's O command (open line above), tmux's pane re-layout, and any less-style scroll-up-by-N. Counterpart is DL (\x1b[Pn M). Terminfo cap: il1 (Pn=1) or il (parameterised).

Spec citation: ECMA-48 §8.3.67 (IL)

Examples

bash
# Set scroll region rows 1..5, position cursor at row 3, insert 2 blank lines.\nprintf '\033[1;5r\033[3;1H\033[2L'
python
import sys; sys.stdout.write('\x1b[2L')   # insert 2 lines at cursor row
go
fmt.Print("\x1b[2L")
javascript
process.stdout.write('\x1b[2L')
c
printf("\x1b[2L");

Used in

Real-world tools that emit this sequence — anchors the bytes to commands you've already used.

  • vim, neovim — `O` (open line above) primitiveevery `O` / `o` / `:put!` boils down to `\x1b[1L` at the cursor row inside a DECSTBM-bracketed region — the editor reuses the terminal's native insert-line rather than redrawing every row below the cursor
  • less, more — scroll-up by Nscrolling backward through a long file emits `\x1b[<N>L` at row 1 inside the page region — the bottom N lines fall off, and the freshly-revealed top lines are then written into the blank slots
  • tmux — pane resize / split-window redrawgrowing a pane vertically uses IL inside the new pane's DECSTBM region to make room without forcing the surrounding panes through a full repaint — `tmux send-keys` benchmarks show ~10× fewer bytes vs. full-screen rewrite
  • ncurses — `insertln()` / `winsertln()`the libncurses API `insertln(WIN)` maps directly to `il1` (no Pn) or `il` (with Pn) terminfo capabilities — every TUI built on ncurses (htop, vifm, mc, weechat) inherits IL the moment the underlying terminal exports the cap
  • git diff --color-moved=zebra inside `less -R`the zebra stripe colouring on moved-block diff hunks works because `less` lays them out with IL + DL pairs inside a DECSTBM region — interleaving the alternating background colours without smearing the unchanged context

Frequently asked

Short answers to the questions developers actually search for this sequence.

Does \x1b[L insert a line or scroll the screen?
Insert. IL (\x1b[Pn L) opens Pn blank lines *at the cursor row* and pushes subsequent rows down within the active scroll region — no scrolling of the top of the region, no content loss above the cursor. Lines that get pushed past the bottom of the scroll region (set by decstbm) are discarded; if you haven't set a scroll region, the bottom lines fall off the visible screen. This is the primitive vim / neovim use for the O and o commands; rolling your own with \n re-implements the bug ed(1) ships with.
How does IL interact with the scroll region (DECSTBM)?
IL only takes effect when the cursor sits *inside* the active scroll region. If the cursor is above the top margin or below the bottom margin, IL is a no-op on most terminals (xterm, kitty, alacritty, wezterm, ghostty) — your draw silently fails to open lines. Inside the region, lines push down toward the bottom margin and any rows past the margin are discarded. The portable pattern is: set DECSTBM (\x1b[<top>;<bottom>r) → move the cursor inside with CUP → emit IL → reset DECSTBM with \x1b[r (defaults to full screen) when done. See pitfall alt-screen-newline for a related cursor-row off-by-one trap.

Terminal support

xterm
yes
Linux console (fbcon)
yes
macOS Terminal.app
yes
iTerm2
yes
Windows Terminal
yes
cmd.exe / ConPTY
partial
kitty
yes
alacritty
yes
WezTerm
yes
Ghostty
yes
GNOME Terminal
yes
Konsole
yes
tmux
yes
GNU screen
yes

Related sequences

In the family cookbook

CSI cookbook · 6. Insert / delete / cursor shape — IL / DL / ICH / DCH / ECH + DECSCUSR