termenv
lets you safely use advanced styling options on the terminal. It
gathers information about the terminal environment in terms of its ANSI & color
support and offers you convenient methods to colorize and style your output,
without you having to deal with all kinds of weird ANSI escape sequences and
color conversions.
- RGB/TrueColor support
- Detects the supported color range of your terminal
- Automatically converts colors to the best matching, available colors
- Terminal theme (light/dark) detection
- Chainable syntax
- Nested styles
go get github.com/muesli/termenv
output := termenv.NewOutput(os.Stdout)
termenv
queries the terminal's capabilities it is running in, so you can
safely use advanced features, like RGB colors or ANSI styles. output.Profile
returns the supported profile:
termenv.Ascii
- no ANSI support detected, ASCII onlytermenv.ANSI
- 16 color ANSI supporttermenv.ANSI256
- Extended 256 color ANSI supporttermenv.TrueColor
- RGB/TrueColor support
Alternatively, you can use termenv.EnvColorProfile
which evaluates the
terminal like ColorProfile
, but also respects the NO_COLOR
and
CLICOLOR_FORCE
environment variables.
You can also query the terminal for its color scheme, so you know whether your app is running in a light- or dark-themed environment:
// Returns terminal's foreground color
color := output.ForegroundColor()
// Returns terminal's background color
color := output.BackgroundColor()
// Returns whether terminal uses a dark-ish background
darkTheme := output.HasDarkBackground()
If you don't want to rely on the automatic detection, you can manually select the profile you want to use:
output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
termenv
supports multiple color profiles: Ascii (black & white only),
ANSI (16 colors), ANSI Extended (256 colors), and TrueColor (24-bit RGB). Colors
will automatically be degraded to the best matching available color in the
desired profile:
TrueColor
=> ANSI 256 Colors
=> ANSI 16 Colors
=> Ascii
s := output.String("Hello World")
// Supports hex values
// Will automatically degrade colors on terminals not supporting RGB
s.Foreground(output.Color("#abcdef"))
// but also supports ANSI colors (0-255)
s.Background(output.Color("69"))
// ...or the color.Color interface
s.Foreground(output.FromColor(color.RGBA{255, 128, 0, 255}))
// Combine fore- & background colors
s.Foreground(output.Color("#ffffff")).Background(output.Color("#0000ff"))
// Supports the fmt.Stringer interface
fmt.Println(s)
You can use a chainable syntax to compose your own styles:
s := output.String("foobar")
// Text styles
s.Bold()
s.Faint()
s.Italic()
s.CrossOut()
s.Underline()
s.Overline()
// Reverse swaps current fore- & background colors
s.Reverse()
// Blinking text
s.Blink()
// Combine multiple options
s.Bold().Underline()
termenv
provides a set of helper functions to style your Go templates:
// load template helpers
f := output.TemplateFuncs()
tpl := template.New("tpl").Funcs(f)
// apply bold style in a template
bold := `{{ Bold "Hello World" }}`
// examples for colorized templates
col := `{{ Color "#ff0000" "#0000ff" "Red on Blue" }}`
fg := `{{ Foreground "#ff0000" "Red Foreground" }}`
bg := `{{ Background "#0000ff" "Blue Background" }}`
// wrap styles
wrap := `{{ Bold (Underline "Hello World") }}`
// parse and render
tpl, err = tpl.Parse(bold)
var buf bytes.Buffer
tpl.Execute(&buf, nil)
fmt.Println(&buf)
Other available helper functions are: Faint
, Italic
, CrossOut
,
Underline
, Overline
, Reverse
, and Blink
.
// Move the cursor to a given position
output.MoveCursor(row, column)
// Save the cursor position
output.SaveCursorPosition()
// Restore a saved cursor position
output.RestoreCursorPosition()
// Move the cursor up a given number of lines
output.CursorUp(n)
// Move the cursor down a given number of lines
output.CursorDown(n)
// Move the cursor up a given number of lines
output.CursorForward(n)
// Move the cursor backwards a given number of cells
output.CursorBack(n)
// Move the cursor down a given number of lines and place it at the beginning
// of the line
output.CursorNextLine(n)
// Move the cursor up a given number of lines and place it at the beginning of
// the line
output.CursorPrevLine(n)
// Reset the terminal to its default style, removing any active styles
output.Reset()
// RestoreScreen restores a previously saved screen state
output.RestoreScreen()
// SaveScreen saves the screen state
output.SaveScreen()
// Switch to the altscreen. The former view can be restored with ExitAltScreen()
output.AltScreen()
// Exit the altscreen and return to the former terminal view
output.ExitAltScreen()
// Clear the visible portion of the terminal
output.ClearScreen()
// Clear the current line
output.ClearLine()
// Clear a given number of lines
output.ClearLines(n)
// Set the scrolling region of the terminal
output.ChangeScrollingRegion(top, bottom)
// Insert the given number of lines at the top of the scrollable region, pushing
// lines below down
output.InsertLines(n)
// Delete the given number of lines, pulling any lines in the scrollable region
// below up
output.DeleteLines(n)
// SetWindowTitle sets the terminal window title
output.SetWindowTitle(title)
// SetForegroundColor sets the default foreground color
output.SetForegroundColor(color)
// SetBackgroundColor sets the default background color
output.SetBackgroundColor(color)
// SetCursorColor sets the cursor color
output.SetCursorColor(color)
// Hide the cursor
output.HideCursor()
// Show the cursor
output.ShowCursor()
// Copy to clipboard
output.Copy(message)
// Copy to primary clipboard (X11)
output.CopyPrimary(message)
// Trigger notification
output.Notify(title, body)
// Enable X10 mouse mode, only button press events are sent
output.EnableMousePress()
// Disable X10 mouse mode
output.DisableMousePress()
// Enable Mouse Tracking mode
output.EnableMouse()
// Disable Mouse Tracking mode
output.DisableMouse()
// Enable Hilite Mouse Tracking mode
output.EnableMouseHilite()
// Disable Hilite Mouse Tracking mode
output.DisableMouseHilite()
// Enable Cell Motion Mouse Tracking mode
output.EnableMouseCellMotion()
// Disable Cell Motion Mouse Tracking mode
output.DisableMouseCellMotion()
// Enable All Motion Mouse mode
output.EnableMouseAllMotion()
// Disable All Motion Mouse mode
output.DisableMouseAllMotion()
// Enables bracketed paste mode
termenv.EnableBracketedPaste()
// Disables bracketed paste mode
termenv.DisableBracketedPaste()
- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Ghostty, Windows Terminal
- 8-bit (256): rxvt, screen, xterm, Apple Terminal
- 4-bit (16): Linux Console
Click to show feature matrix
Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) |
---|---|---|---|---|---|---|---|---|---|
alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
screen | ⛔1 | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
tmux | ⛔1 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
vte-based2 | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
You can help improve this list! Check out how to and open an issue or pull request.
Click to show feature matrix
Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
---|---|---|---|
alacritty | ✅ | ✅3 | ❌ |
foot | ✅ | ✅ | ✅ |
kitty | ✅ | ✅ | ✅ |
Konsole | ❌4 | ✅ | ❌ |
rxvt | ❌ | ❌ | ❌ |
urxvt | ✅5 | ❌ | ✅ |
screen | ✅ | ❌6 | ❌ |
st | ✅ | ❌ | ❌ |
tmux | ✅ | ❌7 | ❌ |
vte-based2 | ❌2 | ✅ | ❌ |
wezterm | ✅ | ✅ | ❌ |
xterm | ✅ | ❌ | ❌ |
Linux Console | ⛔ | ⛔ | ❌ |
Apple Terminal | ✅8 | ❌ | ❌ |
iTerm | ✅ | ✅ | ❌ |
Windows cmd | ❌ | ❌ | ❌ |
Windows Terminal | ✅ | ✅ | ❌ |
termenv
works on Unix systems (like Linux, macOS, or BSD) and Windows. While
terminal applications on Unix support ANSI styling out-of-the-box, on Windows
you need to enable ANSI processing in your application first:
restoreConsole, err := termenv.EnableVirtualTerminalProcessing(termenv.DefaultOutput())
if err != nil {
panic(err)
}
defer restoreConsole()
The above code is safe to include on non-Windows systems or when os.Stdout does not refer to a terminal (e.g. in tests).
You can find the source code used to create this chart in termenv
's examples.
- reflow - ANSI-aware text operations
- Lip Gloss - style definitions for nice terminal layouts 👄
- ansi - ANSI sequence helpers
Need some inspiration or just want to see how others are using termenv
? Check
out these projects:
- Bubble Tea - a powerful little TUI framework 🏗
- Glamour - stylesheet-based markdown rendering for your CLI apps 💇🏻♀️
- Glow - a markdown renderer for the command-line 💅🏻
- duf - Disk Usage/Free Utility - a better 'df' alternative
- gitty - contextual information about your git projects
- slides - terminal-based presentation tool
Got some feedback or suggestions? Please open an issue or drop me a note!
Footnotes
-
Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time. ↩ ↩2
-
This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. ↩ ↩2 ↩3
-
OSC52 is not supported, for more info see bug#372116. ↩
-
Workaround for urxvt not supporting OSC52. See this for more information. ↩
-
OSC52 works with a workaround. ↩