XTPUSHSGR / XTPOPSGR / XTREPORTSGR — SGR stack (CSI Ps + p / + q / + r)
Save / restore / inspect the current SGR attributes via a stack — the SGR analogue of XTPUSHCOLORS for the palette.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[#{ (XTPUSHSGR, alt: CSI Pm + p) \x1b[#} (XTPOPSGR, alt: CSI + q) \x1b[+r (XTREPORTSGR)\033[#{ / \033[#}\e[#{ / \e[#}ESC [ Pm + p / ESC [ + q / ESC [ + r1b 5b ... 2b 70 / 2b 71 / 2b 72Description
Three xterm extensions for stacking SGR (Select Graphic Rendition) state — bold / italic / underline / fg-color / bg-color / blink / strike / reverse, the full set tracked by `sgr-reset`. **XTPUSHSGR** has two equivalent forms: short `\x1b[#{` saves the entire current SGR snapshot, or long `\x1b[<Pm>+p` saves only the named attribute(s) in `Pm` (`1` bold, `3` italic, `4` underline, `5` blink, `7` reverse, `9` strike, `30-37`/`40-47`/`38`/`48` colors). **XTPOPSGR** (`\x1b[#}` short, `\x1b[+q` long) restores the top stack entry — emitted SGR attributes are the difference between current and saved state, applied automatically. **XTREPORTSGR** (`\x1b[+r`) returns the stack depth as a reply `\x1b[<depth>+r`. The two-byte intermediate `#{` and `#}` short forms exist because they're shorter than the long form and parser-friendlier (no parameters to parse). Useful for libraries / TUI primitives that locally mutate SGR (e.g. dim every line except the focused one) without losing the parent context: push → mutate → render → pop. Note that xterm SGR stack and color-palette stack (`xtpushcolors-popcolors`) are SEPARATE stacks — pushing one doesn't push the other. Support is xterm-only; kitty / wezterm / ghostty silently ignore (kitty's CSI u keyboard protocol coincidentally uses `+` as an intermediate but has a different meaning).
Spec citation: xterm-ctlseqs (XTPUSHSGR / XTPOPSGR / XTREPORTSGR)
Parameters
| Pm | Optional list of SGR attribute codes to save (long-form push only). Omitted = save all current SGR state. |
Examples
printf '\033[1;31m' # bold red\nprintf '\033[#{' # push current SGR\nprintf '\033[0;34mlinkified word\033[#}' # mutate, render, pop → bold red restored\necho ' continues bold red'import sys\nsys.stdout.write('\x1b[#{') # save all SGR\nsys.stdout.write('\x1b[2;33mdim yellow status')\nsys.stdout.write('\x1b[#}') # restore parent SGR// Save only foreground color (long form):\nfmt.Print("\x1b[38+p") // push fg\nfmt.Print("\x1b[31malert\x1b[+q") // pop restores fgprocess.stdout.write('\x1b[+r') // query stack depth — reply: \x1b[<n>+rprintf("\x1b[#{"); /* push */\nprintf("\x1b[7m local highlight \x1b[#}"); /* pop restores */Terminal support
- xterm
- yes
- Linux console (fbcon)
- no
- macOS Terminal.app
- no
- iTerm2
- no
- Windows Terminal
- no
- cmd.exe / ConPTY
- no
- kitty
- no
- alacritty
- no
- WezTerm
- no
- Ghostty
- no
- GNOME Terminal
- no
- Konsole
- no
- tmux
- no
- GNU screen
- no
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | no | no | no | no | no | no | no | no | no | no | no | no | no |