1<p align="center">
2 <img src="https://stuff.charm.sh/termenv.png" width="480" alt="termenv Logo">
3 <br />
4 <a href="https://github.com/muesli/termenv/releases"><img src="https://img.shields.io/github/release/muesli/termenv.svg" alt="Latest Release"></a>
5 <a href="https://godoc.org/github.com/muesli/termenv"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a>
6 <a href="https://github.com/muesli/termenv/actions"><img src="https://github.com/muesli/termenv/workflows/build/badge.svg" alt="Build Status"></a>
7 <a href="https://coveralls.io/github/muesli/termenv?branch=master"><img src="https://coveralls.io/repos/github/muesli/termenv/badge.svg?branch=master" alt="Coverage Status"></a>
8 <a href="https://goreportcard.com/report/muesli/termenv"><img src="https://goreportcard.com/badge/muesli/termenv" alt="Go ReportCard"></a>
9 <br />
10 <img src="https://github.com/muesli/termenv/raw/master/examples/hello-world/hello-world.png" alt="Example terminal output">
11</p>
12
13`termenv` lets you safely use advanced styling options on the terminal. It
14gathers information about the terminal environment in terms of its ANSI & color
15support and offers you convenient methods to colorize and style your output,
16without you having to deal with all kinds of weird ANSI escape sequences and
17color conversions.
18
19## Features
20
21- RGB/TrueColor support
22- Detects the supported color range of your terminal
23- Automatically converts colors to the best matching, available colors
24- Terminal theme (light/dark) detection
25- Chainable syntax
26- Nested styles
27
28## Installation
29
30```bash
31go get github.com/muesli/termenv
32```
33
34## Usage
35
36```go
37output := termenv.NewOutput(os.Stdout)
38```
39
40`termenv` queries the terminal's capabilities it is running in, so you can
41safely use advanced features, like RGB colors or ANSI styles. `output.Profile`
42returns the supported profile:
43
44- `termenv.Ascii` - no ANSI support detected, ASCII only
45- `termenv.ANSI` - 16 color ANSI support
46- `termenv.ANSI256` - Extended 256 color ANSI support
47- `termenv.TrueColor` - RGB/TrueColor support
48
49Alternatively, you can use `termenv.EnvColorProfile` which evaluates the
50terminal like `ColorProfile`, but also respects the `NO_COLOR` and
51`CLICOLOR_FORCE` environment variables.
52
53You can also query the terminal for its color scheme, so you know whether your
54app is running in a light- or dark-themed environment:
55
56```go
57// Returns terminal's foreground color
58color := output.ForegroundColor()
59
60// Returns terminal's background color
61color := output.BackgroundColor()
62
63// Returns whether terminal uses a dark-ish background
64darkTheme := output.HasDarkBackground()
65```
66
67### Manual Profile Selection
68
69If you don't want to rely on the automatic detection, you can manually select
70the profile you want to use:
71
72```go
73output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
74```
75
76## Colors
77
78`termenv` supports multiple color profiles: Ascii (black & white only),
79ANSI (16 colors), ANSI Extended (256 colors), and TrueColor (24-bit RGB). Colors
80will automatically be degraded to the best matching available color in the
81desired profile:
82
83`TrueColor` => `ANSI 256 Colors` => `ANSI 16 Colors` => `Ascii`
84
85```go
86s := output.String("Hello World")
87
88// Supports hex values
89// Will automatically degrade colors on terminals not supporting RGB
90s.Foreground(output.Color("#abcdef"))
91// but also supports ANSI colors (0-255)
92s.Background(output.Color("69"))
93// ...or the color.Color interface
94s.Foreground(output.FromColor(color.RGBA{255, 128, 0, 255}))
95
96// Combine fore- & background colors
97s.Foreground(output.Color("#ffffff")).Background(output.Color("#0000ff"))
98
99// Supports the fmt.Stringer interface
100fmt.Println(s)
101```
102
103## Styles
104
105You can use a chainable syntax to compose your own styles:
106
107```go
108s := output.String("foobar")
109
110// Text styles
111s.Bold()
112s.Faint()
113s.Italic()
114s.CrossOut()
115s.Underline()
116s.Overline()
117
118// Reverse swaps current fore- & background colors
119s.Reverse()
120
121// Blinking text
122s.Blink()
123
124// Combine multiple options
125s.Bold().Underline()
126```
127
128## Template Helpers
129
130`termenv` provides a set of helper functions to style your Go templates:
131
132```go
133// load template helpers
134f := output.TemplateFuncs()
135tpl := template.New("tpl").Funcs(f)
136
137// apply bold style in a template
138bold := `{{ Bold "Hello World" }}`
139
140// examples for colorized templates
141col := `{{ Color "#ff0000" "#0000ff" "Red on Blue" }}`
142fg := `{{ Foreground "#ff0000" "Red Foreground" }}`
143bg := `{{ Background "#0000ff" "Blue Background" }}`
144
145// wrap styles
146wrap := `{{ Bold (Underline "Hello World") }}`
147
148// parse and render
149tpl, err = tpl.Parse(bold)
150
151var buf bytes.Buffer
152tpl.Execute(&buf, nil)
153fmt.Println(&buf)
154```
155
156Other available helper functions are: `Faint`, `Italic`, `CrossOut`,
157`Underline`, `Overline`, `Reverse`, and `Blink`.
158
159## Positioning
160
161```go
162// Move the cursor to a given position
163output.MoveCursor(row, column)
164
165// Save the cursor position
166output.SaveCursorPosition()
167
168// Restore a saved cursor position
169output.RestoreCursorPosition()
170
171// Move the cursor up a given number of lines
172output.CursorUp(n)
173
174// Move the cursor down a given number of lines
175output.CursorDown(n)
176
177// Move the cursor up a given number of lines
178output.CursorForward(n)
179
180// Move the cursor backwards a given number of cells
181output.CursorBack(n)
182
183// Move the cursor down a given number of lines and place it at the beginning
184// of the line
185output.CursorNextLine(n)
186
187// Move the cursor up a given number of lines and place it at the beginning of
188// the line
189output.CursorPrevLine(n)
190```
191
192## Screen
193
194```go
195// Reset the terminal to its default style, removing any active styles
196output.Reset()
197
198// RestoreScreen restores a previously saved screen state
199output.RestoreScreen()
200
201// SaveScreen saves the screen state
202output.SaveScreen()
203
204// Switch to the altscreen. The former view can be restored with ExitAltScreen()
205output.AltScreen()
206
207// Exit the altscreen and return to the former terminal view
208output.ExitAltScreen()
209
210// Clear the visible portion of the terminal
211output.ClearScreen()
212
213// Clear the current line
214output.ClearLine()
215
216// Clear a given number of lines
217output.ClearLines(n)
218
219// Set the scrolling region of the terminal
220output.ChangeScrollingRegion(top, bottom)
221
222// Insert the given number of lines at the top of the scrollable region, pushing
223// lines below down
224output.InsertLines(n)
225
226// Delete the given number of lines, pulling any lines in the scrollable region
227// below up
228output.DeleteLines(n)
229```
230
231## Session
232
233```go
234// SetWindowTitle sets the terminal window title
235output.SetWindowTitle(title)
236
237// SetForegroundColor sets the default foreground color
238output.SetForegroundColor(color)
239
240// SetBackgroundColor sets the default background color
241output.SetBackgroundColor(color)
242
243// SetCursorColor sets the cursor color
244output.SetCursorColor(color)
245
246// Hide the cursor
247output.HideCursor()
248
249// Show the cursor
250output.ShowCursor()
251
252// Copy to clipboard
253output.Copy(message)
254
255// Copy to primary clipboard (X11)
256output.CopyPrimary(message)
257
258// Trigger notification
259output.Notify(title, body)
260```
261
262## Mouse
263
264```go
265// Enable X10 mouse mode, only button press events are sent
266output.EnableMousePress()
267
268// Disable X10 mouse mode
269output.DisableMousePress()
270
271// Enable Mouse Tracking mode
272output.EnableMouse()
273
274// Disable Mouse Tracking mode
275output.DisableMouse()
276
277// Enable Hilite Mouse Tracking mode
278output.EnableMouseHilite()
279
280// Disable Hilite Mouse Tracking mode
281output.DisableMouseHilite()
282
283// Enable Cell Motion Mouse Tracking mode
284output.EnableMouseCellMotion()
285
286// Disable Cell Motion Mouse Tracking mode
287output.DisableMouseCellMotion()
288
289// Enable All Motion Mouse mode
290output.EnableMouseAllMotion()
291
292// Disable All Motion Mouse mode
293output.DisableMouseAllMotion()
294```
295
296## Bracketed Paste
297
298```go
299// Enables bracketed paste mode
300termenv.EnableBracketedPaste()
301
302// Disables bracketed paste mode
303termenv.DisableBracketedPaste()
304```
305
306## Terminal Feature Support
307
308### Color Support
309
310- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Windows Terminal
311- 8-bit (256): rxvt, screen, xterm, Apple Terminal
312- 4-bit (16): Linux Console
313
314### Control Sequences
315
316<details>
317<summary>Click to show feature matrix</summary>
318
319| 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) |
320| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: |
321| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
322| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
323| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
324| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
325| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
326| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
327| screen | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
328| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
329| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
330| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
331| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
332| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
333| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
334| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
335| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
336| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
337| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
338
339[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal.
340[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time.
341
342You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
343
344</details>
345
346### System Commands
347
348<details>
349<summary>Click to show feature matrix</summary>
350
351| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
352| ---------------- | :-----------------------: | :---------------: | :--------------------: |
353| alacritty | ✅ | ❌[^alacritty] | ❌ |
354| foot | ✅ | ✅ | ✅ |
355| kitty | ✅ | ✅ | ✅ |
356| Konsole | ❌[^konsole] | ✅ | ❌ |
357| rxvt | ❌ | ❌ | ❌ |
358| urxvt | ✅[^urxvt] | ❌ | ✅ |
359| screen | ✅ | ❌[^screen] | ❌ |
360| st | ✅ | ❌ | ❌ |
361| tmux | ✅ | ❌[^tmux] | ❌ |
362| vte-based[^vte] | ❌[^vte] | ✅ | ❌ |
363| wezterm | ✅ | ✅ | ❌ |
364| xterm | ✅ | ❌ | ❌ |
365| Linux Console | ⛔ | ⛔ | ❌ |
366| Apple Terminal | ✅[^apple] | ❌ | ❌ |
367| iTerm | ✅ | ✅ | ❌ |
368| Windows cmd | ❌ | ❌ | ❌ |
369| Windows Terminal | ✅ | ✅ | ❌ |
370
371[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495).
372[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information.
373[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116).
374[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty).
375[^tmux]: OSC8 is not supported, for more info see [issue#911](https://github.com/tmux/tmux/issues/911).
376[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952).
377[^alacritty]: OSC8 is not supported, for more info see [issue#922](https://github.com/alacritty/alacritty/issues/922).
378
379</details>
380
381## Platform Support
382
383`termenv` works on Unix systems (like Linux, macOS, or BSD) and Windows. While
384terminal applications on Unix support ANSI styling out-of-the-box, on Windows
385you need to enable ANSI processing in your application first:
386
387```go
388 restoreConsole, err := termenv.EnableVirtualTerminalProcessing(termenv.DefaultOutput())
389 if err != nil {
390 panic(err)
391 }
392 defer restoreConsole()
393```
394
395The above code is safe to include on non-Windows systems or when os.Stdout does
396not refer to a terminal (e.g. in tests).
397
398## Color Chart
399
400
401
402You can find the source code used to create this chart in `termenv`'s examples.
403
404## Related Projects
405
406- [reflow](https://github.com/muesli/reflow) - ANSI-aware text operations
407- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - style definitions for nice terminal layouts 👄
408- [ansi](https://github.com/muesli/ansi) - ANSI sequence helpers
409
410## termenv in the Wild
411
412Need some inspiration or just want to see how others are using `termenv`? Check
413out these projects:
414
415- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - a powerful little TUI framework 🏗
416- [Glamour](https://github.com/charmbracelet/glamour) - stylesheet-based markdown rendering for your CLI apps 💇🏻♀️
417- [Glow](https://github.com/charmbracelet/glow) - a markdown renderer for the command-line 💅🏻
418- [duf](https://github.com/muesli/duf) - Disk Usage/Free Utility - a better 'df' alternative
419- [gitty](https://github.com/muesli/gitty) - contextual information about your git projects
420- [slides](https://github.com/maaslalani/slides) - terminal-based presentation tool
421
422## Feedback
423
424Got some feedback or suggestions? Please open an issue or drop me a note!
425
426- [Twitter](https://twitter.com/mueslix)
427- [The Fediverse](https://mastodon.social/@fribbledom)
428
429## License
430
431[MIT](https://github.com/muesli/termenv/raw/master/LICENSE)
View as plain text