summaryrefslogtreecommitdiff
path: root/vendor/github.com/muesli
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
committermo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
commit20ef0d92694465ac86b550df139e8366a0a2b4fa (patch)
tree3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/muesli
parent44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff)
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/muesli')
-rw-r--r--vendor/github.com/muesli/termenv/.gitignore15
-rw-r--r--vendor/github.com/muesli/termenv/.golangci-soft.yml43
-rw-r--r--vendor/github.com/muesli/termenv/.golangci.yml28
-rw-r--r--vendor/github.com/muesli/termenv/LICENSE21
-rw-r--r--vendor/github.com/muesli/termenv/README.md431
-rw-r--r--vendor/github.com/muesli/termenv/ansi_compat.md65
-rw-r--r--vendor/github.com/muesli/termenv/ansicolors.go281
-rw-r--r--vendor/github.com/muesli/termenv/color.go205
-rw-r--r--vendor/github.com/muesli/termenv/constants_linux.go8
-rw-r--r--vendor/github.com/muesli/termenv/constants_solaris.go8
-rw-r--r--vendor/github.com/muesli/termenv/constants_unix.go13
-rw-r--r--vendor/github.com/muesli/termenv/constants_zos.go8
-rw-r--r--vendor/github.com/muesli/termenv/copy.go37
-rw-r--r--vendor/github.com/muesli/termenv/hyperlink.go11
-rw-r--r--vendor/github.com/muesli/termenv/notification.go11
-rw-r--r--vendor/github.com/muesli/termenv/output.go205
-rw-r--r--vendor/github.com/muesli/termenv/profile.go112
-rw-r--r--vendor/github.com/muesli/termenv/screen.go590
-rw-r--r--vendor/github.com/muesli/termenv/style.go126
-rw-r--r--vendor/github.com/muesli/termenv/templatehelper.go88
-rw-r--r--vendor/github.com/muesli/termenv/termenv.go115
-rw-r--r--vendor/github.com/muesli/termenv/termenv_other.go30
-rw-r--r--vendor/github.com/muesli/termenv/termenv_posix.go17
-rw-r--r--vendor/github.com/muesli/termenv/termenv_solaris.go22
-rw-r--r--vendor/github.com/muesli/termenv/termenv_unix.go301
-rw-r--r--vendor/github.com/muesli/termenv/termenv_windows.go140
26 files changed, 2931 insertions, 0 deletions
diff --git a/vendor/github.com/muesli/termenv/.gitignore b/vendor/github.com/muesli/termenv/.gitignore
new file mode 100644
index 0000000..66fd13c
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/.gitignore
@@ -0,0 +1,15 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
diff --git a/vendor/github.com/muesli/termenv/.golangci-soft.yml b/vendor/github.com/muesli/termenv/.golangci-soft.yml
new file mode 100644
index 0000000..84e3d41
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/.golangci-soft.yml
@@ -0,0 +1,43 @@
+run:
+ tests: false
+
+issues:
+ include:
+ - EXC0001
+ - EXC0005
+ - EXC0011
+ - EXC0012
+ - EXC0013
+
+ max-issues-per-linter: 0
+ max-same-issues: 0
+
+linters:
+ enable:
+ # - dupl
+ - exhaustive
+ # - exhaustivestruct
+ - goconst
+ - godot
+ - godox
+ - mnd
+ - gomoddirectives
+ - goprintffuncname
+ # - lll
+ - misspell
+ - nakedret
+ - nestif
+ - noctx
+ - nolintlint
+ - prealloc
+ - wrapcheck
+
+ # disable default linters, they are already enabled in .golangci.yml
+ disable:
+ - errcheck
+ - gosimple
+ - govet
+ - ineffassign
+ - staticcheck
+ - typecheck
+ - unused
diff --git a/vendor/github.com/muesli/termenv/.golangci.yml b/vendor/github.com/muesli/termenv/.golangci.yml
new file mode 100644
index 0000000..684d54b
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/.golangci.yml
@@ -0,0 +1,28 @@
+run:
+ tests: false
+
+issues:
+ include:
+ - EXC0001
+ - EXC0005
+ - EXC0011
+ - EXC0012
+ - EXC0013
+
+ max-issues-per-linter: 0
+ max-same-issues: 0
+
+linters:
+ enable:
+ - bodyclose
+ - goimports
+ - gosec
+ - nilerr
+ - predeclared
+ - revive
+ - rowserrcheck
+ - sqlclosecheck
+ - tparallel
+ - unconvert
+ - unparam
+ - whitespace
diff --git a/vendor/github.com/muesli/termenv/LICENSE b/vendor/github.com/muesli/termenv/LICENSE
new file mode 100644
index 0000000..8532c45
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Christian Muehlhaeuser
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/muesli/termenv/README.md b/vendor/github.com/muesli/termenv/README.md
new file mode 100644
index 0000000..fa7929d
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/README.md
@@ -0,0 +1,431 @@
+<p align="center">
+ <img src="https://stuff.charm.sh/termenv.png" width="480" alt="termenv Logo">
+ <br />
+ <a href="https://github.com/muesli/termenv/releases"><img src="https://img.shields.io/github/release/muesli/termenv.svg" alt="Latest Release"></a>
+ <a href="https://godoc.org/github.com/muesli/termenv"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a>
+ <a href="https://github.com/muesli/termenv/actions"><img src="https://github.com/muesli/termenv/workflows/build/badge.svg" alt="Build Status"></a>
+ <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>
+ <a href="https://goreportcard.com/report/muesli/termenv"><img src="https://goreportcard.com/badge/muesli/termenv" alt="Go ReportCard"></a>
+ <br />
+ <img src="https://github.com/muesli/termenv/raw/master/examples/hello-world/hello-world.png" alt="Example terminal output">
+</p>
+
+`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.
+
+## Features
+
+- 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
+
+## Installation
+
+```bash
+go get github.com/muesli/termenv
+```
+
+## Usage
+
+```go
+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 only
+- `termenv.ANSI` - 16 color ANSI support
+- `termenv.ANSI256` - Extended 256 color ANSI support
+- `termenv.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:
+
+```go
+// 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()
+```
+
+### Manual Profile Selection
+
+If you don't want to rely on the automatic detection, you can manually select
+the profile you want to use:
+
+```go
+output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
+```
+
+## Colors
+
+`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`
+
+```go
+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)
+```
+
+## Styles
+
+You can use a chainable syntax to compose your own styles:
+
+```go
+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()
+```
+
+## Template Helpers
+
+`termenv` provides a set of helper functions to style your Go templates:
+
+```go
+// 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`.
+
+## Positioning
+
+```go
+// 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)
+```
+
+## Screen
+
+```go
+// 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)
+```
+
+## Session
+
+```go
+// 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)
+```
+
+## Mouse
+
+```go
+// 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()
+```
+
+## Bracketed Paste
+
+```go
+// Enables bracketed paste mode
+termenv.EnableBracketedPaste()
+
+// Disables bracketed paste mode
+termenv.DisableBracketedPaste()
+```
+
+## Terminal Feature Support
+
+### Color Support
+
+- 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
+
+### Control Sequences
+
+<details>
+<summary>Click to show feature matrix</summary>
+
+| 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 | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
+| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
+| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
+| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
+| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+
+[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal.
+[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time.
+
+You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
+
+</details>
+
+### System Commands
+
+<details>
+<summary>Click to show feature matrix</summary>
+
+| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
+| ---------------- | :-----------------------: | :---------------: | :--------------------: |
+| alacritty | ✅ | ✅[^alacritty] | ❌ |
+| foot | ✅ | ✅ | ✅ |
+| kitty | ✅ | ✅ | ✅ |
+| Konsole | ❌[^konsole] | ✅ | ❌ |
+| rxvt | ❌ | ❌ | ❌ |
+| urxvt | ✅[^urxvt] | ❌ | ✅ |
+| screen | ✅ | ❌[^screen] | ❌ |
+| st | ✅ | ❌ | ❌ |
+| tmux | ✅ | ❌[^tmux] | ❌ |
+| vte-based[^vte] | ❌[^vte] | ✅ | ❌ |
+| wezterm | ✅ | ✅ | ❌ |
+| xterm | ✅ | ❌ | ❌ |
+| Linux Console | ⛔ | ⛔ | ❌ |
+| Apple Terminal | ✅[^apple] | ❌ | ❌ |
+| iTerm | ✅ | ✅ | ❌ |
+| Windows cmd | ❌ | ❌ | ❌ |
+| Windows Terminal | ✅ | ✅ | ❌ |
+
+[^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).
+[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information.
+[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116).
+[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty).
+[^tmux]: OSC8 is not supported, for more info see [issue#911](https://github.com/tmux/tmux/issues/911).
+[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952).
+[^alacritty]: OSC8 is supported since [v0.11.0](https://github.com/alacritty/alacritty/releases/tag/v0.11.0)
+
+</details>
+
+## Platform Support
+
+`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:
+
+```go
+ 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).
+
+## Color Chart
+
+![ANSI color chart](https://github.com/muesli/termenv/raw/master/examples/color-chart/color-chart.png)
+
+You can find the source code used to create this chart in `termenv`'s examples.
+
+## Related Projects
+
+- [reflow](https://github.com/muesli/reflow) - ANSI-aware text operations
+- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - style definitions for nice terminal layouts 👄
+- [ansi](https://github.com/muesli/ansi) - ANSI sequence helpers
+
+## termenv in the Wild
+
+Need some inspiration or just want to see how others are using `termenv`? Check
+out these projects:
+
+- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - a powerful little TUI framework 🏗
+- [Glamour](https://github.com/charmbracelet/glamour) - stylesheet-based markdown rendering for your CLI apps 💇🏻‍♀️
+- [Glow](https://github.com/charmbracelet/glow) - a markdown renderer for the command-line 💅🏻
+- [duf](https://github.com/muesli/duf) - Disk Usage/Free Utility - a better 'df' alternative
+- [gitty](https://github.com/muesli/gitty) - contextual information about your git projects
+- [slides](https://github.com/maaslalani/slides) - terminal-based presentation tool
+
+## Feedback
+
+Got some feedback or suggestions? Please open an issue or drop me a note!
+
+- [Twitter](https://twitter.com/mueslix)
+- [The Fediverse](https://mastodon.social/@fribbledom)
+
+## License
+
+[MIT](https://github.com/muesli/termenv/raw/master/LICENSE)
diff --git a/vendor/github.com/muesli/termenv/ansi_compat.md b/vendor/github.com/muesli/termenv/ansi_compat.md
new file mode 100644
index 0000000..6b68a3a
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/ansi_compat.md
@@ -0,0 +1,65 @@
+## Change Foreground Color
+
+This command should enable a blue foreground color:
+
+```bash
+echo -ne "\033]10;#0000ff\007"
+```
+
+## Change Background Color
+
+This command should enable a green background color:
+
+```bash
+echo -ne "\033]11;#00ff00\007"
+```
+
+## Change Cursor Color
+
+This command should enable a red cursor color:
+
+```bash
+echo -ne "\033]12;#ff0000\007"
+```
+
+## Query Color Scheme
+
+These two commands should print out the currently active color scheme:
+
+```bash
+echo -ne "\033]10;?\033\\"
+echo -ne "\033]11;?\033\\"
+```
+
+## Query Cursor Position
+
+This command should print out the current cursor position:
+
+```bash
+echo -ne "\033[6n"
+```
+
+## Set Window Title
+
+This command should set the window title to "Test":
+
+```bash
+echo -ne "\033]2;Test\007" && sleep 10
+```
+
+## Bracketed paste
+
+Enter this command, then paste a word from the clipboard. The text
+displayed on the terminal should contain the codes `200~` and `201~`:
+
+```bash
+echo -ne "\033[?2004h" && sleep 10
+```
+
+## Trigger Notification
+
+This command should trigger a notification:
+
+```bash
+echo -ne "\033]777;notify;Title;Body\033\\"
+```
diff --git a/vendor/github.com/muesli/termenv/ansicolors.go b/vendor/github.com/muesli/termenv/ansicolors.go
new file mode 100644
index 0000000..1a301b0
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/ansicolors.go
@@ -0,0 +1,281 @@
+package termenv
+
+// ANSI color codes.
+const (
+ ANSIBlack ANSIColor = iota
+ ANSIRed
+ ANSIGreen
+ ANSIYellow
+ ANSIBlue
+ ANSIMagenta
+ ANSICyan
+ ANSIWhite
+ ANSIBrightBlack
+ ANSIBrightRed
+ ANSIBrightGreen
+ ANSIBrightYellow
+ ANSIBrightBlue
+ ANSIBrightMagenta
+ ANSIBrightCyan
+ ANSIBrightWhite
+)
+
+// RGB values of ANSI colors (0-255).
+var ansiHex = []string{
+ "#000000",
+ "#800000",
+ "#008000",
+ "#808000",
+ "#000080",
+ "#800080",
+ "#008080",
+ "#c0c0c0",
+ "#808080",
+ "#ff0000",
+ "#00ff00",
+ "#ffff00",
+ "#0000ff",
+ "#ff00ff",
+ "#00ffff",
+ "#ffffff",
+ "#000000",
+ "#00005f",
+ "#000087",
+ "#0000af",
+ "#0000d7",
+ "#0000ff",
+ "#005f00",
+ "#005f5f",
+ "#005f87",
+ "#005faf",
+ "#005fd7",
+ "#005fff",
+ "#008700",
+ "#00875f",
+ "#008787",
+ "#0087af",
+ "#0087d7",
+ "#0087ff",
+ "#00af00",
+ "#00af5f",
+ "#00af87",
+ "#00afaf",
+ "#00afd7",
+ "#00afff",
+ "#00d700",
+ "#00d75f",
+ "#00d787",
+ "#00d7af",
+ "#00d7d7",
+ "#00d7ff",
+ "#00ff00",
+ "#00ff5f",
+ "#00ff87",
+ "#00ffaf",
+ "#00ffd7",
+ "#00ffff",
+ "#5f0000",
+ "#5f005f",
+ "#5f0087",
+ "#5f00af",
+ "#5f00d7",
+ "#5f00ff",
+ "#5f5f00",
+ "#5f5f5f",
+ "#5f5f87",
+ "#5f5faf",
+ "#5f5fd7",
+ "#5f5fff",
+ "#5f8700",
+ "#5f875f",
+ "#5f8787",
+ "#5f87af",
+ "#5f87d7",
+ "#5f87ff",
+ "#5faf00",
+ "#5faf5f",
+ "#5faf87",
+ "#5fafaf",
+ "#5fafd7",
+ "#5fafff",
+ "#5fd700",
+ "#5fd75f",
+ "#5fd787",
+ "#5fd7af",
+ "#5fd7d7",
+ "#5fd7ff",
+ "#5fff00",
+ "#5fff5f",
+ "#5fff87",
+ "#5fffaf",
+ "#5fffd7",
+ "#5fffff",
+ "#870000",
+ "#87005f",
+ "#870087",
+ "#8700af",
+ "#8700d7",
+ "#8700ff",
+ "#875f00",
+ "#875f5f",
+ "#875f87",
+ "#875faf",
+ "#875fd7",
+ "#875fff",
+ "#878700",
+ "#87875f",
+ "#878787",
+ "#8787af",
+ "#8787d7",
+ "#8787ff",
+ "#87af00",
+ "#87af5f",
+ "#87af87",
+ "#87afaf",
+ "#87afd7",
+ "#87afff",
+ "#87d700",
+ "#87d75f",
+ "#87d787",
+ "#87d7af",
+ "#87d7d7",
+ "#87d7ff",
+ "#87ff00",
+ "#87ff5f",
+ "#87ff87",
+ "#87ffaf",
+ "#87ffd7",
+ "#87ffff",
+ "#af0000",
+ "#af005f",
+ "#af0087",
+ "#af00af",
+ "#af00d7",
+ "#af00ff",
+ "#af5f00",
+ "#af5f5f",
+ "#af5f87",
+ "#af5faf",
+ "#af5fd7",
+ "#af5fff",
+ "#af8700",
+ "#af875f",
+ "#af8787",
+ "#af87af",
+ "#af87d7",
+ "#af87ff",
+ "#afaf00",
+ "#afaf5f",
+ "#afaf87",
+ "#afafaf",
+ "#afafd7",
+ "#afafff",
+ "#afd700",
+ "#afd75f",
+ "#afd787",
+ "#afd7af",
+ "#afd7d7",
+ "#afd7ff",
+ "#afff00",
+ "#afff5f",
+ "#afff87",
+ "#afffaf",
+ "#afffd7",
+ "#afffff",
+ "#d70000",
+ "#d7005f",
+ "#d70087",
+ "#d700af",
+ "#d700d7",
+ "#d700ff",
+ "#d75f00",
+ "#d75f5f",
+ "#d75f87",
+ "#d75faf",
+ "#d75fd7",
+ "#d75fff",
+ "#d78700",
+ "#d7875f",
+ "#d78787",
+ "#d787af",
+ "#d787d7",
+ "#d787ff",
+ "#d7af00",
+ "#d7af5f",
+ "#d7af87",
+ "#d7afaf",
+ "#d7afd7",
+ "#d7afff",
+ "#d7d700",
+ "#d7d75f",
+ "#d7d787",
+ "#d7d7af",
+ "#d7d7d7",
+ "#d7d7ff",
+ "#d7ff00",
+ "#d7ff5f",
+ "#d7ff87",
+ "#d7ffaf",
+ "#d7ffd7",
+ "#d7ffff",
+ "#ff0000",
+ "#ff005f",
+ "#ff0087",
+ "#ff00af",
+ "#ff00d7",
+ "#ff00ff",
+ "#ff5f00",
+ "#ff5f5f",
+ "#ff5f87",
+ "#ff5faf",
+ "#ff5fd7",
+ "#ff5fff",
+ "#ff8700",
+ "#ff875f",
+ "#ff8787",
+ "#ff87af",
+ "#ff87d7",
+ "#ff87ff",
+ "#ffaf00",
+ "#ffaf5f",
+ "#ffaf87",
+ "#ffafaf",
+ "#ffafd7",
+ "#ffafff",
+ "#ffd700",
+ "#ffd75f",
+ "#ffd787",
+ "#ffd7af",
+ "#ffd7d7",
+ "#ffd7ff",
+ "#ffff00",
+ "#ffff5f",
+ "#ffff87",
+ "#ffffaf",
+ "#ffffd7",
+ "#ffffff",
+ "#080808",
+ "#121212",
+ "#1c1c1c",
+ "#262626",
+ "#303030",
+ "#3a3a3a",
+ "#444444",
+ "#4e4e4e",
+ "#585858",
+ "#626262",
+ "#6c6c6c",
+ "#767676",
+ "#808080",
+ "#8a8a8a",
+ "#949494",
+ "#9e9e9e",
+ "#a8a8a8",
+ "#b2b2b2",
+ "#bcbcbc",
+ "#c6c6c6",
+ "#d0d0d0",
+ "#dadada",
+ "#e4e4e4",
+ "#eeeeee",
+}
diff --git a/vendor/github.com/muesli/termenv/color.go b/vendor/github.com/muesli/termenv/color.go
new file mode 100644
index 0000000..59e639b
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/color.go
@@ -0,0 +1,205 @@
+package termenv
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "strings"
+
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// ErrInvalidColor gets returned when a color is invalid.
+var ErrInvalidColor = errors.New("invalid color")
+
+// Foreground and Background sequence codes.
+const (
+ Foreground = "38"
+ Background = "48"
+)
+
+// Color is an interface implemented by all colors that can be converted to an
+// ANSI sequence.
+type Color interface {
+ // Sequence returns the ANSI Sequence for the color.
+ Sequence(bg bool) string
+}
+
+// NoColor is a nop for terminals that don't support colors.
+type NoColor struct{}
+
+func (c NoColor) String() string {
+ return ""
+}
+
+// ANSIColor is a color (0-15) as defined by the ANSI Standard.
+type ANSIColor int
+
+func (c ANSIColor) String() string {
+ return ansiHex[c]
+}
+
+// ANSI256Color is a color (16-255) as defined by the ANSI Standard.
+type ANSI256Color int
+
+func (c ANSI256Color) String() string {
+ return ansiHex[c]
+}
+
+// RGBColor is a hex-encoded color, e.g. "#abcdef".
+type RGBColor string
+
+// ConvertToRGB converts a Color to a colorful.Color.
+func ConvertToRGB(c Color) colorful.Color {
+ var hex string
+ switch v := c.(type) {
+ case RGBColor:
+ hex = string(v)
+ case ANSIColor:
+ hex = ansiHex[v]
+ case ANSI256Color:
+ hex = ansiHex[v]
+ }
+
+ ch, _ := colorful.Hex(hex)
+ return ch
+}
+
+// Sequence returns the ANSI Sequence for the color.
+func (c NoColor) Sequence(_ bool) string {
+ return ""
+}
+
+// Sequence returns the ANSI Sequence for the color.
+//
+//nolint:mnd
+func (c ANSIColor) Sequence(bg bool) string {
+ col := int(c)
+ bgMod := func(c int) int {
+ if bg {
+ return c + 10
+ }
+ return c
+ }
+
+ if col < 8 {
+ return fmt.Sprintf("%d", bgMod(col)+30) //nolint:mnd
+ }
+ return fmt.Sprintf("%d", bgMod(col-8)+90) //nolint:mnd
+}
+
+// Sequence returns the ANSI Sequence for the color.
+func (c ANSI256Color) Sequence(bg bool) string {
+ prefix := Foreground
+ if bg {
+ prefix = Background
+ }
+ return fmt.Sprintf("%s;5;%d", prefix, c)
+}
+
+// Sequence returns the ANSI Sequence for the color.
+func (c RGBColor) Sequence(bg bool) string {
+ f, err := colorful.Hex(string(c))
+ if err != nil {
+ return ""
+ }
+
+ prefix := Foreground
+ if bg {
+ prefix = Background
+ }
+ return fmt.Sprintf("%s;2;%d;%d;%d", prefix, uint8(f.R*255), uint8(f.G*255), uint8(f.B*255)) //nolint:mnd
+}
+
+func xTermColor(s string) (RGBColor, error) {
+ if len(s) < 24 || len(s) > 25 {
+ return RGBColor(""), ErrInvalidColor
+ }
+
+ switch {
+ case strings.HasSuffix(s, string(BEL)):
+ s = strings.TrimSuffix(s, string(BEL))
+ case strings.HasSuffix(s, string(ESC)):
+ s = strings.TrimSuffix(s, string(ESC))
+ case strings.HasSuffix(s, ST):
+ s = strings.TrimSuffix(s, ST)
+ default:
+ return RGBColor(""), ErrInvalidColor
+ }
+
+ s = s[4:]
+
+ prefix := ";rgb:"
+ if !strings.HasPrefix(s, prefix) {
+ return RGBColor(""), ErrInvalidColor
+ }
+ s = strings.TrimPrefix(s, prefix)
+
+ h := strings.Split(s, "/")
+ hex := fmt.Sprintf("#%s%s%s", h[0][:2], h[1][:2], h[2][:2])
+ return RGBColor(hex), nil
+}
+
+func ansi256ToANSIColor(c ANSI256Color) ANSIColor {
+ var r int
+ md := math.MaxFloat64
+
+ h, _ := colorful.Hex(ansiHex[c])
+ for i := 0; i <= 15; i++ {
+ hb, _ := colorful.Hex(ansiHex[i])
+ d := h.DistanceHSLuv(hb)
+
+ if d < md {
+ md = d
+ r = i
+ }
+ }
+
+ return ANSIColor(r)
+}
+
+//nolint:mnd
+func hexToANSI256Color(c colorful.Color) ANSI256Color {
+ v2ci := func(v float64) int {
+ if v < 48 {
+ return 0
+ }
+ if v < 115 {
+ return 1
+ }
+ return int((v - 35) / 40)
+ }
+
+ // Calculate the nearest 0-based color index at 16..231
+ r := v2ci(c.R * 255.0) // 0..5 each
+ g := v2ci(c.G * 255.0)
+ b := v2ci(c.B * 255.0)
+ ci := 36*r + 6*g + b /* 0..215 */
+
+ // Calculate the represented colors back from the index
+ i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
+ cr := i2cv[r] // r/g/b, 0..255 each
+ cg := i2cv[g]
+ cb := i2cv[b]
+
+ // Calculate the nearest 0-based gray index at 232..255
+ var grayIdx int
+ average := (r + g + b) / 3
+ if average > 238 {
+ grayIdx = 23
+ } else {
+ grayIdx = (average - 3) / 10 // 0..23
+ }
+ gv := 8 + 10*grayIdx // same value for r/g/b, 0..255
+
+ // Return the one which is nearer to the original input rgb value
+ c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0}
+ g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0}
+ colorDist := c.DistanceHSLuv(c2)
+ grayDist := c.DistanceHSLuv(g2)
+
+ if colorDist <= grayDist {
+ return ANSI256Color(16 + ci)
+ }
+ return ANSI256Color(232 + grayIdx)
+}
diff --git a/vendor/github.com/muesli/termenv/constants_linux.go b/vendor/github.com/muesli/termenv/constants_linux.go
new file mode 100644
index 0000000..4262f03
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/constants_linux.go
@@ -0,0 +1,8 @@
+package termenv
+
+import "golang.org/x/sys/unix"
+
+const (
+ tcgetattr = unix.TCGETS
+ tcsetattr = unix.TCSETS
+)
diff --git a/vendor/github.com/muesli/termenv/constants_solaris.go b/vendor/github.com/muesli/termenv/constants_solaris.go
new file mode 100644
index 0000000..4262f03
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/constants_solaris.go
@@ -0,0 +1,8 @@
+package termenv
+
+import "golang.org/x/sys/unix"
+
+const (
+ tcgetattr = unix.TCGETS
+ tcsetattr = unix.TCSETS
+)
diff --git a/vendor/github.com/muesli/termenv/constants_unix.go b/vendor/github.com/muesli/termenv/constants_unix.go
new file mode 100644
index 0000000..5d66424
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/constants_unix.go
@@ -0,0 +1,13 @@
+//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && !solaris && !illumos
+// +build darwin dragonfly freebsd netbsd openbsd
+// +build !solaris
+// +build !illumos
+
+package termenv
+
+import "golang.org/x/sys/unix"
+
+const (
+ tcgetattr = unix.TIOCGETA
+ tcsetattr = unix.TIOCSETA
+)
diff --git a/vendor/github.com/muesli/termenv/constants_zos.go b/vendor/github.com/muesli/termenv/constants_zos.go
new file mode 100644
index 0000000..4262f03
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/constants_zos.go
@@ -0,0 +1,8 @@
+package termenv
+
+import "golang.org/x/sys/unix"
+
+const (
+ tcgetattr = unix.TCGETS
+ tcsetattr = unix.TCSETS
+)
diff --git a/vendor/github.com/muesli/termenv/copy.go b/vendor/github.com/muesli/termenv/copy.go
new file mode 100644
index 0000000..4bf5c9f
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/copy.go
@@ -0,0 +1,37 @@
+package termenv
+
+import (
+ "strings"
+
+ "github.com/aymanbagabas/go-osc52/v2"
+)
+
+// Copy copies text to clipboard using OSC 52 escape sequence.
+func (o Output) Copy(str string) {
+ s := osc52.New(str)
+ if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
+ s = s.Screen()
+ }
+ _, _ = s.WriteTo(o)
+}
+
+// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
+// sequence.
+func (o Output) CopyPrimary(str string) {
+ s := osc52.New(str).Primary()
+ if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
+ s = s.Screen()
+ }
+ _, _ = s.WriteTo(o)
+}
+
+// Copy copies text to clipboard using OSC 52 escape sequence.
+func Copy(str string) {
+ output.Copy(str)
+}
+
+// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
+// sequence.
+func CopyPrimary(str string) {
+ output.CopyPrimary(str)
+}
diff --git a/vendor/github.com/muesli/termenv/hyperlink.go b/vendor/github.com/muesli/termenv/hyperlink.go
new file mode 100644
index 0000000..97e760a
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/hyperlink.go
@@ -0,0 +1,11 @@
+package termenv
+
+// Hyperlink creates a hyperlink using OSC8.
+func Hyperlink(link, name string) string {
+ return output.Hyperlink(link, name)
+}
+
+// Hyperlink creates a hyperlink using OSC8.
+func (o *Output) Hyperlink(link, name string) string {
+ return OSC + "8;;" + link + ST + name + OSC + "8;;" + ST
+}
diff --git a/vendor/github.com/muesli/termenv/notification.go b/vendor/github.com/muesli/termenv/notification.go
new file mode 100644
index 0000000..2a8cf06
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/notification.go
@@ -0,0 +1,11 @@
+package termenv
+
+// Notify triggers a notification using OSC777.
+func Notify(title, body string) {
+ output.Notify(title, body)
+}
+
+// Notify triggers a notification using OSC777.
+func (o *Output) Notify(title, body string) {
+ _, _ = o.WriteString(OSC + "777;notify;" + title + ";" + body + ST)
+}
diff --git a/vendor/github.com/muesli/termenv/output.go b/vendor/github.com/muesli/termenv/output.go
new file mode 100644
index 0000000..e4434de
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/output.go
@@ -0,0 +1,205 @@
+package termenv
+
+import (
+ "io"
+ "os"
+ "sync"
+)
+
+// output is the default global output.
+var output = NewOutput(os.Stdout)
+
+// File represents a file descriptor.
+//
+// Deprecated: Use *os.File instead.
+type File interface {
+ io.ReadWriter
+ Fd() uintptr
+}
+
+// OutputOption sets an option on Output.
+type OutputOption = func(*Output)
+
+// Output is a terminal output.
+type Output struct {
+ Profile
+ w io.Writer
+ environ Environ
+
+ assumeTTY bool
+ unsafe bool
+ cache bool
+ fgSync *sync.Once
+ fgColor Color
+ bgSync *sync.Once
+ bgColor Color
+}
+
+// Environ is an interface for getting environment variables.
+type Environ interface {
+ Environ() []string
+ Getenv(string) string
+}
+
+type osEnviron struct{}
+
+func (oe *osEnviron) Environ() []string {
+ return os.Environ()
+}
+
+func (oe *osEnviron) Getenv(key string) string {
+ return os.Getenv(key)
+}
+
+// DefaultOutput returns the default global output.
+func DefaultOutput() *Output {
+ return output
+}
+
+// SetDefaultOutput sets the default global output.
+func SetDefaultOutput(o *Output) {
+ output = o
+}
+
+// NewOutput returns a new Output for the given writer.
+func NewOutput(w io.Writer, opts ...OutputOption) *Output {
+ o := &Output{
+ w: w,
+ environ: &osEnviron{},
+ Profile: -1,
+ fgSync: &sync.Once{},
+ fgColor: NoColor{},
+ bgSync: &sync.Once{},
+ bgColor: NoColor{},
+ }
+
+ if o.w == nil {
+ o.w = os.Stdout
+ }
+ for _, opt := range opts {
+ opt(o)
+ }
+ if o.Profile < 0 {
+ o.Profile = o.EnvColorProfile()
+ }
+
+ return o
+}
+
+// WithEnvironment returns a new OutputOption for the given environment.
+func WithEnvironment(environ Environ) OutputOption {
+ return func(o *Output) {
+ o.environ = environ
+ }
+}
+
+// WithProfile returns a new OutputOption for the given profile.
+func WithProfile(profile Profile) OutputOption {
+ return func(o *Output) {
+ o.Profile = profile
+ }
+}
+
+// WithColorCache returns a new OutputOption with fore- and background color values
+// pre-fetched and cached.
+func WithColorCache(v bool) OutputOption {
+ return func(o *Output) {
+ o.cache = v
+
+ // cache the values now
+ _ = o.ForegroundColor()
+ _ = o.BackgroundColor()
+ }
+}
+
+// WithTTY returns a new OutputOption to assume whether or not the output is a TTY.
+// This is useful when mocking console output.
+func WithTTY(v bool) OutputOption {
+ return func(o *Output) {
+ o.assumeTTY = v
+ }
+}
+
+// WithUnsafe returns a new OutputOption with unsafe mode enabled. Unsafe mode doesn't
+// check whether or not the terminal is a TTY.
+//
+// This option supersedes WithTTY.
+//
+// This is useful when mocking console output and enforcing ANSI escape output
+// e.g. on SSH sessions.
+func WithUnsafe() OutputOption {
+ return func(o *Output) {
+ o.unsafe = true
+ }
+}
+
+// ForegroundColor returns the terminal's default foreground color.
+func (o *Output) ForegroundColor() Color {
+ f := func() {
+ if !o.isTTY() {
+ return
+ }
+
+ o.fgColor = o.foregroundColor()
+ }
+
+ if o.cache {
+ o.fgSync.Do(f)
+ } else {
+ f()
+ }
+
+ return o.fgColor
+}
+
+// BackgroundColor returns the terminal's default background color.
+func (o *Output) BackgroundColor() Color {
+ f := func() {
+ if !o.isTTY() {
+ return
+ }
+
+ o.bgColor = o.backgroundColor()
+ }
+
+ if o.cache {
+ o.bgSync.Do(f)
+ } else {
+ f()
+ }
+
+ return o.bgColor
+}
+
+// HasDarkBackground returns whether terminal uses a dark-ish background.
+func (o *Output) HasDarkBackground() bool {
+ c := ConvertToRGB(o.BackgroundColor())
+ _, _, l := c.Hsl()
+ return l < 0.5 //nolint:mnd
+}
+
+// TTY returns the terminal's file descriptor. This may be nil if the output is
+// not a terminal.
+//
+// Deprecated: Use Writer() instead.
+func (o Output) TTY() File {
+ if f, ok := o.w.(File); ok {
+ return f
+ }
+ return nil
+}
+
+// Writer returns the underlying writer. This may be of type io.Writer,
+// io.ReadWriter, or *os.File.
+func (o Output) Writer() io.Writer {
+ return o.w
+}
+
+func (o Output) Write(p []byte) (int, error) {
+ return o.w.Write(p) //nolint:wrapcheck
+}
+
+// WriteString writes the given string to the output.
+func (o Output) WriteString(s string) (int, error) {
+ return o.Write([]byte(s))
+}
diff --git a/vendor/github.com/muesli/termenv/profile.go b/vendor/github.com/muesli/termenv/profile.go
new file mode 100644
index 0000000..7d38f5f
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/profile.go
@@ -0,0 +1,112 @@
+package termenv
+
+import (
+ "image/color"
+ "strconv"
+ "strings"
+
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// Profile is a color profile: Ascii, ANSI, ANSI256, or TrueColor.
+type Profile int
+
+const (
+ // TrueColor, 24-bit color profile.
+ TrueColor = Profile(iota)
+ // ANSI256, 8-bit color profile.
+ ANSI256
+ // ANSI, 4-bit color profile.
+ ANSI
+ // Ascii, uncolored profile.
+ Ascii //nolint:revive
+)
+
+// Name returns the profile name as a string.
+func (p Profile) Name() string {
+ switch p {
+ case Ascii:
+ return "Ascii"
+ case ANSI:
+ return "ANSI"
+ case ANSI256:
+ return "ANSI256"
+ case TrueColor:
+ return "TrueColor"
+ }
+ return "Unknown"
+}
+
+// String returns a new Style.
+func (p Profile) String(s ...string) Style {
+ return Style{
+ profile: p,
+ string: strings.Join(s, " "),
+ }
+}
+
+// Convert transforms a given Color to a Color supported within the Profile.
+func (p Profile) Convert(c Color) Color {
+ if p == Ascii {
+ return NoColor{}
+ }
+
+ switch v := c.(type) {
+ case ANSIColor:
+ return v
+
+ case ANSI256Color:
+ if p == ANSI {
+ return ansi256ToANSIColor(v)
+ }
+ return v
+
+ case RGBColor:
+ h, err := colorful.Hex(string(v))
+ if err != nil {
+ return nil
+ }
+ if p != TrueColor {
+ ac := hexToANSI256Color(h)
+ if p == ANSI {
+ return ansi256ToANSIColor(ac)
+ }
+ return ac
+ }
+ return v
+ }
+
+ return c
+}
+
+// Color creates a Color from a string. Valid inputs are hex colors, as well as
+// ANSI color codes (0-15, 16-255).
+func (p Profile) Color(s string) Color {
+ if len(s) == 0 {
+ return nil
+ }
+
+ var c Color
+ if strings.HasPrefix(s, "#") {
+ c = RGBColor(s)
+ } else {
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ return nil
+ }
+
+ if i < 16 { //nolint:mnd
+ c = ANSIColor(i)
+ } else {
+ c = ANSI256Color(i)
+ }
+ }
+
+ return p.Convert(c)
+}
+
+// FromColor creates a Color from a color.Color.
+func (p Profile) FromColor(c color.Color) Color {
+ col, _ := colorful.MakeColor(c)
+ return p.Color(col.Hex())
+}
diff --git a/vendor/github.com/muesli/termenv/screen.go b/vendor/github.com/muesli/termenv/screen.go
new file mode 100644
index 0000000..75c11d0
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/screen.go
@@ -0,0 +1,590 @@
+package termenv
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Sequence definitions.
+const (
+ // Cursor positioning.
+ CursorUpSeq = "%dA"
+ CursorDownSeq = "%dB"
+ CursorForwardSeq = "%dC"
+ CursorBackSeq = "%dD"
+ CursorNextLineSeq = "%dE"
+ CursorPreviousLineSeq = "%dF"
+ CursorHorizontalSeq = "%dG"
+ CursorPositionSeq = "%d;%dH"
+ EraseDisplaySeq = "%dJ"
+ EraseLineSeq = "%dK"
+ ScrollUpSeq = "%dS"
+ ScrollDownSeq = "%dT"
+ SaveCursorPositionSeq = "s"
+ RestoreCursorPositionSeq = "u"
+ ChangeScrollingRegionSeq = "%d;%dr"
+ InsertLineSeq = "%dL"
+ DeleteLineSeq = "%dM"
+
+ // Explicit values for EraseLineSeq.
+ EraseLineRightSeq = "0K"
+ EraseLineLeftSeq = "1K"
+ EraseEntireLineSeq = "2K"
+
+ // Mouse.
+ EnableMousePressSeq = "?9h" // press only (X10)
+ DisableMousePressSeq = "?9l"
+ EnableMouseSeq = "?1000h" // press, release, wheel
+ DisableMouseSeq = "?1000l"
+ EnableMouseHiliteSeq = "?1001h" // highlight
+ DisableMouseHiliteSeq = "?1001l"
+ EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel
+ DisableMouseCellMotionSeq = "?1002l"
+ EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel
+ DisableMouseAllMotionSeq = "?1003l"
+ EnableMouseExtendedModeSeq = "?1006h" // press, release, move, wheel, extended coordinates
+ DisableMouseExtendedModeSeq = "?1006l"
+ EnableMousePixelsModeSeq = "?1016h" // press, release, move, wheel, extended pixel coordinates
+ DisableMousePixelsModeSeq = "?1016l"
+
+ // Screen.
+ RestoreScreenSeq = "?47l"
+ SaveScreenSeq = "?47h"
+ AltScreenSeq = "?1049h"
+ ExitAltScreenSeq = "?1049l"
+
+ // Bracketed paste.
+ // https://en.wikipedia.org/wiki/Bracketed-paste
+ EnableBracketedPasteSeq = "?2004h"
+ DisableBracketedPasteSeq = "?2004l"
+ StartBracketedPasteSeq = "200~"
+ EndBracketedPasteSeq = "201~"
+
+ // Session.
+ SetWindowTitleSeq = "2;%s" + string(BEL)
+ SetForegroundColorSeq = "10;%s" + string(BEL)
+ SetBackgroundColorSeq = "11;%s" + string(BEL)
+ SetCursorColorSeq = "12;%s" + string(BEL)
+ ShowCursorSeq = "?25h"
+ HideCursorSeq = "?25l"
+)
+
+// Reset the terminal to its default style, removing any active styles.
+func (o Output) Reset() {
+ fmt.Fprint(o.w, CSI+ResetSeq+"m") //nolint:errcheck
+}
+
+// SetForegroundColor sets the default foreground color.
+func (o Output) SetForegroundColor(color Color) {
+ fmt.Fprintf(o.w, OSC+SetForegroundColorSeq, color) //nolint:errcheck
+}
+
+// SetBackgroundColor sets the default background color.
+func (o Output) SetBackgroundColor(color Color) {
+ fmt.Fprintf(o.w, OSC+SetBackgroundColorSeq, color) //nolint:errcheck
+}
+
+// SetCursorColor sets the cursor color.
+func (o Output) SetCursorColor(color Color) {
+ fmt.Fprintf(o.w, OSC+SetCursorColorSeq, color) //nolint:errcheck
+}
+
+// RestoreScreen restores a previously saved screen state.
+func (o Output) RestoreScreen() {
+ fmt.Fprint(o.w, CSI+RestoreScreenSeq) //nolint:errcheck
+}
+
+// SaveScreen saves the screen state.
+func (o Output) SaveScreen() {
+ fmt.Fprint(o.w, CSI+SaveScreenSeq) //nolint:errcheck
+}
+
+// AltScreen switches to the alternate screen buffer. The former view can be
+// restored with ExitAltScreen().
+func (o Output) AltScreen() {
+ fmt.Fprint(o.w, CSI+AltScreenSeq) //nolint:errcheck
+}
+
+// ExitAltScreen exits the alternate screen buffer and returns to the former
+// terminal view.
+func (o Output) ExitAltScreen() {
+ fmt.Fprint(o.w, CSI+ExitAltScreenSeq) //nolint:errcheck
+}
+
+// ClearScreen clears the visible portion of the terminal.
+func (o Output) ClearScreen() {
+ fmt.Fprintf(o.w, CSI+EraseDisplaySeq, 2) //nolint:errcheck,mnd
+ o.MoveCursor(1, 1)
+}
+
+// MoveCursor moves the cursor to a given position.
+func (o Output) MoveCursor(row int, column int) {
+ fmt.Fprintf(o.w, CSI+CursorPositionSeq, row, column) //nolint:errcheck
+}
+
+// HideCursor hides the cursor.
+func (o Output) HideCursor() {
+ fmt.Fprint(o.w, CSI+HideCursorSeq) //nolint:errcheck
+}
+
+// ShowCursor shows the cursor.
+func (o Output) ShowCursor() {
+ fmt.Fprint(o.w, CSI+ShowCursorSeq) //nolint:errcheck
+}
+
+// SaveCursorPosition saves the cursor position.
+func (o Output) SaveCursorPosition() {
+ fmt.Fprint(o.w, CSI+SaveCursorPositionSeq) //nolint:errcheck
+}
+
+// RestoreCursorPosition restores a saved cursor position.
+func (o Output) RestoreCursorPosition() {
+ fmt.Fprint(o.w, CSI+RestoreCursorPositionSeq) //nolint:errcheck
+}
+
+// CursorUp moves the cursor up a given number of lines.
+func (o Output) CursorUp(n int) {
+ fmt.Fprintf(o.w, CSI+CursorUpSeq, n) //nolint:errcheck
+}
+
+// CursorDown moves the cursor down a given number of lines.
+func (o Output) CursorDown(n int) {
+ fmt.Fprintf(o.w, CSI+CursorDownSeq, n) //nolint:errcheck
+}
+
+// CursorForward moves the cursor up a given number of lines.
+func (o Output) CursorForward(n int) {
+ fmt.Fprintf(o.w, CSI+CursorForwardSeq, n) //nolint:errcheck
+}
+
+// CursorBack moves the cursor backwards a given number of cells.
+func (o Output) CursorBack(n int) {
+ fmt.Fprintf(o.w, CSI+CursorBackSeq, n) //nolint:errcheck
+}
+
+// CursorNextLine moves the cursor down a given number of lines and places it at
+// the beginning of the line.
+func (o Output) CursorNextLine(n int) {
+ fmt.Fprintf(o.w, CSI+CursorNextLineSeq, n) //nolint:errcheck
+}
+
+// CursorPrevLine moves the cursor up a given number of lines and places it at
+// the beginning of the line.
+func (o Output) CursorPrevLine(n int) {
+ fmt.Fprintf(o.w, CSI+CursorPreviousLineSeq, n) //nolint:errcheck
+}
+
+// ClearLine clears the current line.
+func (o Output) ClearLine() {
+ fmt.Fprint(o.w, CSI+EraseEntireLineSeq) //nolint:errcheck
+}
+
+// ClearLineLeft clears the line to the left of the cursor.
+func (o Output) ClearLineLeft() {
+ fmt.Fprint(o.w, CSI+EraseLineLeftSeq) //nolint:errcheck
+}
+
+// ClearLineRight clears the line to the right of the cursor.
+func (o Output) ClearLineRight() {
+ fmt.Fprint(o.w, CSI+EraseLineRightSeq) //nolint:errcheck
+}
+
+// ClearLines clears a given number of lines.
+func (o Output) ClearLines(n int) {
+ clearLine := fmt.Sprintf(CSI+EraseLineSeq, 2) //nolint:mnd
+ cursorUp := fmt.Sprintf(CSI+CursorUpSeq, 1)
+ fmt.Fprint(o.w, clearLine+strings.Repeat(cursorUp+clearLine, n)) //nolint:errcheck
+}
+
+// ChangeScrollingRegion sets the scrolling region of the terminal.
+func (o Output) ChangeScrollingRegion(top, bottom int) {
+ fmt.Fprintf(o.w, CSI+ChangeScrollingRegionSeq, top, bottom) //nolint:errcheck
+}
+
+// InsertLines inserts the given number of lines at the top of the scrollable
+// region, pushing lines below down.
+func (o Output) InsertLines(n int) {
+ fmt.Fprintf(o.w, CSI+InsertLineSeq, n) //nolint:errcheck
+}
+
+// DeleteLines deletes the given number of lines, pulling any lines in
+// the scrollable region below up.
+func (o Output) DeleteLines(n int) {
+ fmt.Fprintf(o.w, CSI+DeleteLineSeq, n) //nolint:errcheck
+}
+
+// EnableMousePress enables X10 mouse mode. Button press events are sent only.
+func (o Output) EnableMousePress() {
+ fmt.Fprint(o.w, CSI+EnableMousePressSeq) //nolint:errcheck
+}
+
+// DisableMousePress disables X10 mouse mode.
+func (o Output) DisableMousePress() {
+ fmt.Fprint(o.w, CSI+DisableMousePressSeq) //nolint:errcheck
+}
+
+// EnableMouse enables Mouse Tracking mode.
+func (o Output) EnableMouse() {
+ fmt.Fprint(o.w, CSI+EnableMouseSeq) //nolint:errcheck
+}
+
+// DisableMouse disables Mouse Tracking mode.
+func (o Output) DisableMouse() {
+ fmt.Fprint(o.w, CSI+DisableMouseSeq) //nolint:errcheck
+}
+
+// EnableMouseHilite enables Hilite Mouse Tracking mode.
+func (o Output) EnableMouseHilite() {
+ fmt.Fprint(o.w, CSI+EnableMouseHiliteSeq) //nolint:errcheck
+}
+
+// DisableMouseHilite disables Hilite Mouse Tracking mode.
+func (o Output) DisableMouseHilite() {
+ fmt.Fprint(o.w, CSI+DisableMouseHiliteSeq) //nolint:errcheck
+}
+
+// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
+func (o Output) EnableMouseCellMotion() {
+ fmt.Fprint(o.w, CSI+EnableMouseCellMotionSeq) //nolint:errcheck
+}
+
+// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
+func (o Output) DisableMouseCellMotion() {
+ fmt.Fprint(o.w, CSI+DisableMouseCellMotionSeq) //nolint:errcheck
+}
+
+// EnableMouseAllMotion enables All Motion Mouse mode.
+func (o Output) EnableMouseAllMotion() {
+ fmt.Fprint(o.w, CSI+EnableMouseAllMotionSeq) //nolint:errcheck
+}
+
+// DisableMouseAllMotion disables All Motion Mouse mode.
+func (o Output) DisableMouseAllMotion() {
+ fmt.Fprint(o.w, CSI+DisableMouseAllMotionSeq) //nolint:errcheck
+}
+
+// EnableMouseExtendedMotion enables Extended Mouse mode (SGR). This should be
+// enabled in conjunction with EnableMouseCellMotion, and EnableMouseAllMotion.
+func (o Output) EnableMouseExtendedMode() {
+ fmt.Fprint(o.w, CSI+EnableMouseExtendedModeSeq) //nolint:errcheck
+}
+
+// DisableMouseExtendedMotion disables Extended Mouse mode (SGR).
+func (o Output) DisableMouseExtendedMode() {
+ fmt.Fprint(o.w, CSI+DisableMouseExtendedModeSeq) //nolint:errcheck
+}
+
+// EnableMousePixelsMotion enables Pixel Motion Mouse mode (SGR-Pixels). This
+// should be enabled in conjunction with EnableMouseCellMotion, and
+// EnableMouseAllMotion.
+func (o Output) EnableMousePixelsMode() {
+ fmt.Fprint(o.w, CSI+EnableMousePixelsModeSeq) //nolint:errcheck
+}
+
+// DisableMousePixelsMotion disables Pixel Motion Mouse mode (SGR-Pixels).
+func (o Output) DisableMousePixelsMode() {
+ fmt.Fprint(o.w, CSI+DisableMousePixelsModeSeq) //nolint:errcheck
+}
+
+// SetWindowTitle sets the terminal window title.
+func (o Output) SetWindowTitle(title string) {
+ fmt.Fprintf(o.w, OSC+SetWindowTitleSeq, title) //nolint:errcheck
+}
+
+// EnableBracketedPaste enables bracketed paste.
+func (o Output) EnableBracketedPaste() {
+ fmt.Fprintf(o.w, CSI+EnableBracketedPasteSeq) //nolint:errcheck
+}
+
+// DisableBracketedPaste disables bracketed paste.
+func (o Output) DisableBracketedPaste() {
+ fmt.Fprintf(o.w, CSI+DisableBracketedPasteSeq) //nolint:errcheck
+}
+
+// Legacy functions.
+
+// Reset the terminal to its default style, removing any active styles.
+//
+// Deprecated: please use termenv.Output instead.
+func Reset() {
+ output.Reset()
+}
+
+// SetForegroundColor sets the default foreground color.
+//
+// Deprecated: please use termenv.Output instead.
+func SetForegroundColor(color Color) {
+ output.SetForegroundColor(color)
+}
+
+// SetBackgroundColor sets the default background color.
+//
+// Deprecated: please use termenv.Output instead.
+func SetBackgroundColor(color Color) {
+ output.SetBackgroundColor(color)
+}
+
+// SetCursorColor sets the cursor color.
+//
+// Deprecated: please use termenv.Output instead.
+func SetCursorColor(color Color) {
+ output.SetCursorColor(color)
+}
+
+// RestoreScreen restores a previously saved screen state.
+//
+// Deprecated: please use termenv.Output instead.
+func RestoreScreen() {
+ output.RestoreScreen()
+}
+
+// SaveScreen saves the screen state.
+//
+// Deprecated: please use termenv.Output instead.
+func SaveScreen() {
+ output.SaveScreen()
+}
+
+// AltScreen switches to the alternate screen buffer. The former view can be
+// restored with ExitAltScreen().
+//
+// Deprecated: please use termenv.Output instead.
+func AltScreen() {
+ output.AltScreen()
+}
+
+// ExitAltScreen exits the alternate screen buffer and returns to the former
+// terminal view.
+//
+// Deprecated: please use termenv.Output instead.
+func ExitAltScreen() {
+ output.ExitAltScreen()
+}
+
+// ClearScreen clears the visible portion of the terminal.
+//
+// Deprecated: please use termenv.Output instead.
+func ClearScreen() {
+ output.ClearScreen()
+}
+
+// MoveCursor moves the cursor to a given position.
+//
+// Deprecated: please use termenv.Output instead.
+func MoveCursor(row int, column int) {
+ output.MoveCursor(row, column)
+}
+
+// HideCursor hides the cursor.
+//
+// Deprecated: please use termenv.Output instead.
+func HideCursor() {
+ output.HideCursor()
+}
+
+// ShowCursor shows the cursor.
+//
+// Deprecated: please use termenv.Output instead.
+func ShowCursor() {
+ output.ShowCursor()
+}
+
+// SaveCursorPosition saves the cursor position.
+//
+// Deprecated: please use termenv.Output instead.
+func SaveCursorPosition() {
+ output.SaveCursorPosition()
+}
+
+// RestoreCursorPosition restores a saved cursor position.
+//
+// Deprecated: please use termenv.Output instead.
+func RestoreCursorPosition() {
+ output.RestoreCursorPosition()
+}
+
+// CursorUp moves the cursor up a given number of lines.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorUp(n int) {
+ output.CursorUp(n)
+}
+
+// CursorDown moves the cursor down a given number of lines.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorDown(n int) {
+ output.CursorDown(n)
+}
+
+// CursorForward moves the cursor up a given number of lines.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorForward(n int) {
+ output.CursorForward(n)
+}
+
+// CursorBack moves the cursor backwards a given number of cells.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorBack(n int) {
+ output.CursorBack(n)
+}
+
+// CursorNextLine moves the cursor down a given number of lines and places it at
+// the beginning of the line.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorNextLine(n int) {
+ output.CursorNextLine(n)
+}
+
+// CursorPrevLine moves the cursor up a given number of lines and places it at
+// the beginning of the line.
+//
+// Deprecated: please use termenv.Output instead.
+func CursorPrevLine(n int) {
+ output.CursorPrevLine(n)
+}
+
+// ClearLine clears the current line.
+//
+// Deprecated: please use termenv.Output instead.
+func ClearLine() {
+ output.ClearLine()
+}
+
+// ClearLineLeft clears the line to the left of the cursor.
+//
+// Deprecated: please use termenv.Output instead.
+func ClearLineLeft() {
+ output.ClearLineLeft()
+}
+
+// ClearLineRight clears the line to the right of the cursor.
+//
+// Deprecated: please use termenv.Output instead.
+func ClearLineRight() {
+ output.ClearLineRight()
+}
+
+// ClearLines clears a given number of lines.
+//
+// Deprecated: please use termenv.Output instead.
+func ClearLines(n int) {
+ output.ClearLines(n)
+}
+
+// ChangeScrollingRegion sets the scrolling region of the terminal.
+//
+// Deprecated: please use termenv.Output instead.
+func ChangeScrollingRegion(top, bottom int) {
+ output.ChangeScrollingRegion(top, bottom)
+}
+
+// InsertLines inserts the given number of lines at the top of the scrollable
+// region, pushing lines below down.
+//
+// Deprecated: please use termenv.Output instead.
+func InsertLines(n int) {
+ output.InsertLines(n)
+}
+
+// DeleteLines deletes the given number of lines, pulling any lines in
+// the scrollable region below up.
+//
+// Deprecated: please use termenv.Output instead.
+func DeleteLines(n int) {
+ output.DeleteLines(n)
+}
+
+// EnableMousePress enables X10 mouse mode. Button press events are sent only.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableMousePress() {
+ output.EnableMousePress()
+}
+
+// DisableMousePress disables X10 mouse mode.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableMousePress() {
+ output.DisableMousePress()
+}
+
+// EnableMouse enables Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableMouse() {
+ output.EnableMouse()
+}
+
+// DisableMouse disables Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableMouse() {
+ output.DisableMouse()
+}
+
+// EnableMouseHilite enables Hilite Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableMouseHilite() {
+ output.EnableMouseHilite()
+}
+
+// DisableMouseHilite disables Hilite Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableMouseHilite() {
+ output.DisableMouseHilite()
+}
+
+// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableMouseCellMotion() {
+ output.EnableMouseCellMotion()
+}
+
+// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableMouseCellMotion() {
+ output.DisableMouseCellMotion()
+}
+
+// EnableMouseAllMotion enables All Motion Mouse mode.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableMouseAllMotion() {
+ output.EnableMouseAllMotion()
+}
+
+// DisableMouseAllMotion disables All Motion Mouse mode.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableMouseAllMotion() {
+ output.DisableMouseAllMotion()
+}
+
+// SetWindowTitle sets the terminal window title.
+//
+// Deprecated: please use termenv.Output instead.
+func SetWindowTitle(title string) {
+ output.SetWindowTitle(title)
+}
+
+// EnableBracketedPaste enables bracketed paste.
+//
+// Deprecated: please use termenv.Output instead.
+func EnableBracketedPaste() {
+ output.EnableBracketedPaste()
+}
+
+// DisableBracketedPaste disables bracketed paste.
+//
+// Deprecated: please use termenv.Output instead.
+func DisableBracketedPaste() {
+ output.DisableBracketedPaste()
+}
diff --git a/vendor/github.com/muesli/termenv/style.go b/vendor/github.com/muesli/termenv/style.go
new file mode 100644
index 0000000..dedc1f9
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/style.go
@@ -0,0 +1,126 @@
+package termenv
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/rivo/uniseg"
+)
+
+// Sequence definitions.
+const (
+ ResetSeq = "0"
+ BoldSeq = "1"
+ FaintSeq = "2"
+ ItalicSeq = "3"
+ UnderlineSeq = "4"
+ BlinkSeq = "5"
+ ReverseSeq = "7"
+ CrossOutSeq = "9"
+ OverlineSeq = "53"
+)
+
+// Style is a string that various rendering styles can be applied to.
+type Style struct {
+ profile Profile
+ string
+ styles []string
+}
+
+// String returns a new Style.
+func String(s ...string) Style {
+ return Style{
+ profile: ANSI,
+ string: strings.Join(s, " "),
+ }
+}
+
+func (t Style) String() string {
+ return t.Styled(t.string)
+}
+
+// Styled renders s with all applied styles.
+func (t Style) Styled(s string) string {
+ if t.profile == Ascii {
+ return s
+ }
+ if len(t.styles) == 0 {
+ return s
+ }
+
+ seq := strings.Join(t.styles, ";")
+ if seq == "" {
+ return s
+ }
+
+ return fmt.Sprintf("%s%sm%s%sm", CSI, seq, s, CSI+ResetSeq)
+}
+
+// Foreground sets a foreground color.
+func (t Style) Foreground(c Color) Style {
+ if c != nil {
+ t.styles = append(t.styles, c.Sequence(false))
+ }
+ return t
+}
+
+// Background sets a background color.
+func (t Style) Background(c Color) Style {
+ if c != nil {
+ t.styles = append(t.styles, c.Sequence(true))
+ }
+ return t
+}
+
+// Bold enables bold rendering.
+func (t Style) Bold() Style {
+ t.styles = append(t.styles, BoldSeq)
+ return t
+}
+
+// Faint enables faint rendering.
+func (t Style) Faint() Style {
+ t.styles = append(t.styles, FaintSeq)
+ return t
+}
+
+// Italic enables italic rendering.
+func (t Style) Italic() Style {
+ t.styles = append(t.styles, ItalicSeq)
+ return t
+}
+
+// Underline enables underline rendering.
+func (t Style) Underline() Style {
+ t.styles = append(t.styles, UnderlineSeq)
+ return t
+}
+
+// Overline enables overline rendering.
+func (t Style) Overline() Style {
+ t.styles = append(t.styles, OverlineSeq)
+ return t
+}
+
+// Blink enables blink mode.
+func (t Style) Blink() Style {
+ t.styles = append(t.styles, BlinkSeq)
+ return t
+}
+
+// Reverse enables reverse color mode.
+func (t Style) Reverse() Style {
+ t.styles = append(t.styles, ReverseSeq)
+ return t
+}
+
+// CrossOut enables crossed-out rendering.
+func (t Style) CrossOut() Style {
+ t.styles = append(t.styles, CrossOutSeq)
+ return t
+}
+
+// Width returns the width required to print all runes in Style.
+func (t Style) Width() int {
+ return uniseg.StringWidth(t.string)
+}
diff --git a/vendor/github.com/muesli/termenv/templatehelper.go b/vendor/github.com/muesli/termenv/templatehelper.go
new file mode 100644
index 0000000..4c7c80f
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/templatehelper.go
@@ -0,0 +1,88 @@
+package termenv
+
+import (
+ "text/template"
+)
+
+// TemplateFuncs returns template helpers for the given output.
+func (o Output) TemplateFuncs() template.FuncMap {
+ return TemplateFuncs(o.Profile)
+}
+
+// TemplateFuncs contains a few useful template helpers.
+//
+//nolint:mnd
+func TemplateFuncs(p Profile) template.FuncMap {
+ if p == Ascii {
+ return noopTemplateFuncs
+ }
+
+ return template.FuncMap{
+ "Color": func(values ...interface{}) string {
+ s := p.String(values[len(values)-1].(string))
+ switch len(values) {
+ case 2:
+ s = s.Foreground(p.Color(values[0].(string)))
+ case 3:
+ s = s.
+ Foreground(p.Color(values[0].(string))).
+ Background(p.Color(values[1].(string)))
+ }
+
+ return s.String()
+ },
+ "Foreground": func(values ...interface{}) string {
+ s := p.String(values[len(values)-1].(string))
+ if len(values) == 2 {
+ s = s.Foreground(p.Color(values[0].(string)))
+ }
+
+ return s.String()
+ },
+ "Background": func(values ...interface{}) string {
+ s := p.String(values[len(values)-1].(string))
+ if len(values) == 2 {
+ s = s.Background(p.Color(values[0].(string)))
+ }
+
+ return s.String()
+ },
+ "Bold": styleFunc(p, Style.Bold),
+ "Faint": styleFunc(p, Style.Faint),
+ "Italic": styleFunc(p, Style.Italic),
+ "Underline": styleFunc(p, Style.Underline),
+ "Overline": styleFunc(p, Style.Overline),
+ "Blink": styleFunc(p, Style.Blink),
+ "Reverse": styleFunc(p, Style.Reverse),
+ "CrossOut": styleFunc(p, Style.CrossOut),
+ }
+}
+
+func styleFunc(p Profile, f func(Style) Style) func(...interface{}) string {
+ return func(values ...interface{}) string {
+ s := p.String(values[0].(string))
+ return f(s).String()
+ }
+}
+
+var noopTemplateFuncs = template.FuncMap{
+ "Color": noColorFunc,
+ "Foreground": noColorFunc,
+ "Background": noColorFunc,
+ "Bold": noStyleFunc,
+ "Faint": noStyleFunc,
+ "Italic": noStyleFunc,
+ "Underline": noStyleFunc,
+ "Overline": noStyleFunc,
+ "Blink": noStyleFunc,
+ "Reverse": noStyleFunc,
+ "CrossOut": noStyleFunc,
+}
+
+func noColorFunc(values ...interface{}) string {
+ return values[len(values)-1].(string)
+}
+
+func noStyleFunc(values ...interface{}) string {
+ return values[0].(string)
+}
diff --git a/vendor/github.com/muesli/termenv/termenv.go b/vendor/github.com/muesli/termenv/termenv.go
new file mode 100644
index 0000000..d702cd5
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv.go
@@ -0,0 +1,115 @@
+package termenv
+
+import (
+ "errors"
+ "os"
+
+ "github.com/mattn/go-isatty"
+)
+
+var (
+ // ErrStatusReport gets returned when the terminal can't be queried.
+ ErrStatusReport = errors.New("unable to retrieve status report")
+)
+
+const (
+ // Escape character.
+ ESC = '\x1b'
+ // Bell.
+ BEL = '\a'
+ // Control Sequence Introducer.
+ CSI = string(ESC) + "["
+ // Operating System Command.
+ OSC = string(ESC) + "]"
+ // String Terminator.
+ ST = string(ESC) + `\`
+)
+
+func (o *Output) isTTY() bool {
+ if o.assumeTTY || o.unsafe {
+ return true
+ }
+ if len(o.environ.Getenv("CI")) > 0 {
+ return false
+ }
+ if f, ok := o.Writer().(*os.File); ok {
+ return isatty.IsTerminal(f.Fd())
+ }
+
+ return false
+}
+
+// ColorProfile returns the supported color profile:
+// Ascii, ANSI, ANSI256, or TrueColor.
+func ColorProfile() Profile {
+ return output.ColorProfile()
+}
+
+// ForegroundColor returns the terminal's default foreground color.
+func ForegroundColor() Color {
+ return output.ForegroundColor()
+}
+
+// BackgroundColor returns the terminal's default background color.
+func BackgroundColor() Color {
+ return output.BackgroundColor()
+}
+
+// HasDarkBackground returns whether terminal uses a dark-ish background.
+func HasDarkBackground() bool {
+ return output.HasDarkBackground()
+}
+
+// EnvNoColor returns true if the environment variables explicitly disable color output
+// by setting NO_COLOR (https://no-color.org/)
+// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
+// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
+// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
+func (o *Output) EnvNoColor() bool {
+ return o.environ.Getenv("NO_COLOR") != "" || (o.environ.Getenv("CLICOLOR") == "0" && !o.cliColorForced())
+}
+
+// EnvNoColor returns true if the environment variables explicitly disable color output
+// by setting NO_COLOR (https://no-color.org/)
+// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
+// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
+// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
+func EnvNoColor() bool {
+ return output.EnvNoColor()
+}
+
+// EnvColorProfile returns the color profile based on environment variables set
+// Supports NO_COLOR (https://no-color.org/)
+// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
+// If none of these environment variables are set, this behaves the same as ColorProfile()
+// It will return the Ascii color profile if EnvNoColor() returns true
+// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
+// then the ANSI color profile will be returned.
+func EnvColorProfile() Profile {
+ return output.EnvColorProfile()
+}
+
+// EnvColorProfile returns the color profile based on environment variables set
+// Supports NO_COLOR (https://no-color.org/)
+// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
+// If none of these environment variables are set, this behaves the same as ColorProfile()
+// It will return the Ascii color profile if EnvNoColor() returns true
+// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
+// then the ANSI color profile will be returned.
+func (o *Output) EnvColorProfile() Profile {
+ if o.EnvNoColor() {
+ return Ascii
+ }
+ p := o.ColorProfile()
+ if o.cliColorForced() && p == Ascii {
+ return ANSI
+ }
+ return p
+}
+
+func (o *Output) cliColorForced() bool {
+ if forced := o.environ.Getenv("CLICOLOR_FORCE"); forced != "" {
+ return forced != "0"
+ }
+ return false
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_other.go b/vendor/github.com/muesli/termenv/termenv_other.go
new file mode 100644
index 0000000..93a43b6
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv_other.go
@@ -0,0 +1,30 @@
+//go:build js || plan9 || aix
+// +build js plan9 aix
+
+package termenv
+
+import "io"
+
+// ColorProfile returns the supported color profile:
+// ANSI256
+func (o Output) ColorProfile() Profile {
+ return ANSI256
+}
+
+func (o Output) foregroundColor() Color {
+ // default gray
+ return ANSIColor(7)
+}
+
+func (o Output) backgroundColor() Color {
+ // default black
+ return ANSIColor(0)
+}
+
+// EnableVirtualTerminalProcessing enables virtual terminal processing on
+// Windows for w and returns a function that restores w to its previous state.
+// On non-Windows platforms, or if w does not refer to a terminal, then it
+// returns a non-nil no-op function and no error.
+func EnableVirtualTerminalProcessing(w io.Writer) (func() error, error) {
+ return func() error { return nil }, nil
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_posix.go b/vendor/github.com/muesli/termenv/termenv_posix.go
new file mode 100644
index 0000000..c971dd9
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv_posix.go
@@ -0,0 +1,17 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos
+// +build darwin dragonfly freebsd linux netbsd openbsd zos
+
+package termenv
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+func isForeground(fd int) bool {
+ pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
+ if err != nil {
+ return false
+ }
+
+ return pgrp == unix.Getpgrp()
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_solaris.go b/vendor/github.com/muesli/termenv/termenv_solaris.go
new file mode 100644
index 0000000..27a95a9
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv_solaris.go
@@ -0,0 +1,22 @@
+//go:build solaris || illumos
+// +build solaris illumos
+
+package termenv
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+func isForeground(fd int) bool {
+ pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
+ if err != nil {
+ return false
+ }
+
+ g, err := unix.Getpgrp()
+ if err != nil {
+ return false
+ }
+
+ return pgrp == g
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_unix.go b/vendor/github.com/muesli/termenv/termenv_unix.go
new file mode 100644
index 0000000..bef49ca
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv_unix.go
@@ -0,0 +1,301 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris zos
+
+package termenv
+
+import (
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+const (
+ // timeout for OSC queries.
+ OSCTimeout = 5 * time.Second
+)
+
+// ColorProfile returns the supported color profile:
+// Ascii, ANSI, ANSI256, or TrueColor.
+func (o *Output) ColorProfile() Profile {
+ if !o.isTTY() {
+ return Ascii
+ }
+
+ if o.environ.Getenv("GOOGLE_CLOUD_SHELL") == "true" {
+ return TrueColor
+ }
+
+ term := o.environ.Getenv("TERM")
+ colorTerm := o.environ.Getenv("COLORTERM")
+
+ switch strings.ToLower(colorTerm) {
+ case "24bit":
+ fallthrough
+ case "truecolor":
+ if strings.HasPrefix(term, "screen") {
+ // tmux supports TrueColor, screen only ANSI256
+ if o.environ.Getenv("TERM_PROGRAM") != "tmux" {
+ return ANSI256
+ }
+ }
+ return TrueColor
+ case "yes":
+ fallthrough
+ case "true":
+ return ANSI256
+ }
+
+ switch term {
+ case
+ "alacritty",
+ "contour",
+ "rio",
+ "wezterm",
+ "xterm-ghostty",
+ "xterm-kitty":
+ return TrueColor
+ case "linux", "xterm":
+ return ANSI
+ }
+
+ if strings.Contains(term, "256color") {
+ return ANSI256
+ }
+ if strings.Contains(term, "color") {
+ return ANSI
+ }
+ if strings.Contains(term, "ansi") {
+ return ANSI
+ }
+
+ return Ascii
+}
+
+//nolint:mnd
+func (o Output) foregroundColor() Color {
+ s, err := o.termStatusReport(10)
+ if err == nil {
+ c, err := xTermColor(s)
+ if err == nil {
+ return c
+ }
+ }
+
+ colorFGBG := o.environ.Getenv("COLORFGBG")
+ if strings.Contains(colorFGBG, ";") {
+ c := strings.Split(colorFGBG, ";")
+ i, err := strconv.Atoi(c[0])
+ if err == nil {
+ return ANSIColor(i)
+ }
+ }
+
+ // default gray
+ return ANSIColor(7)
+}
+
+//nolint:mnd
+func (o Output) backgroundColor() Color {
+ s, err := o.termStatusReport(11)
+ if err == nil {
+ c, err := xTermColor(s)
+ if err == nil {
+ return c
+ }
+ }
+
+ colorFGBG := o.environ.Getenv("COLORFGBG")
+ if strings.Contains(colorFGBG, ";") {
+ c := strings.Split(colorFGBG, ";")
+ i, err := strconv.Atoi(c[len(c)-1])
+ if err == nil {
+ return ANSIColor(i)
+ }
+ }
+
+ // default black
+ return ANSIColor(0)
+}
+
+func (o *Output) waitForData(timeout time.Duration) error {
+ fd := o.TTY().Fd()
+ tv := unix.NsecToTimeval(int64(timeout))
+ var readfds unix.FdSet
+ readfds.Set(int(fd)) //nolint:gosec
+
+ for {
+ n, err := unix.Select(int(fd)+1, &readfds, nil, nil, &tv) //nolint:gosec
+ if err == unix.EINTR {
+ continue
+ }
+ if err != nil {
+ return err //nolint:wrapcheck
+ }
+ if n == 0 {
+ return fmt.Errorf("timeout")
+ }
+
+ break
+ }
+
+ return nil
+}
+
+func (o *Output) readNextByte() (byte, error) {
+ if !o.unsafe {
+ if err := o.waitForData(OSCTimeout); err != nil {
+ return 0, err
+ }
+ }
+
+ var b [1]byte
+ n, err := o.TTY().Read(b[:])
+ if err != nil {
+ return 0, err //nolint:wrapcheck
+ }
+
+ if n == 0 {
+ panic("read returned no data")
+ }
+
+ return b[0], nil
+}
+
+// readNextResponse reads either an OSC response or a cursor position response:
+// - OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\"
+// - cursor position response: "\x1b[42;1R"
+func (o *Output) readNextResponse() (response string, isOSC bool, err error) {
+ start, err := o.readNextByte()
+ if err != nil {
+ return "", false, err
+ }
+
+ // first byte must be ESC
+ for start != ESC {
+ start, err = o.readNextByte()
+ if err != nil {
+ return "", false, err
+ }
+ }
+
+ response += string(start)
+
+ // next byte is either '[' (cursor position response) or ']' (OSC response)
+ tpe, err := o.readNextByte()
+ if err != nil {
+ return "", false, err
+ }
+
+ response += string(tpe)
+
+ var oscResponse bool
+ switch tpe {
+ case '[':
+ oscResponse = false
+ case ']':
+ oscResponse = true
+ default:
+ return "", false, ErrStatusReport
+ }
+
+ for {
+ b, err := o.readNextByte()
+ if err != nil {
+ return "", false, err
+ }
+
+ response += string(b)
+
+ if oscResponse {
+ // OSC can be terminated by BEL (\a) or ST (ESC)
+ if b == BEL || strings.HasSuffix(response, string(ESC)) {
+ return response, true, nil
+ }
+ } else {
+ // cursor position response is terminated by 'R'
+ if b == 'R' {
+ return response, false, nil
+ }
+ }
+
+ // both responses have less than 25 bytes, so if we read more, that's an error
+ if len(response) > 25 { //nolint:mnd
+ break
+ }
+ }
+
+ return "", false, ErrStatusReport
+}
+
+func (o Output) termStatusReport(sequence int) (string, error) {
+ // screen/tmux can't support OSC, because they can be connected to multiple
+ // terminals concurrently.
+ term := o.environ.Getenv("TERM")
+ if strings.HasPrefix(term, "screen") || strings.HasPrefix(term, "tmux") || strings.HasPrefix(term, "dumb") {
+ return "", ErrStatusReport
+ }
+
+ tty := o.TTY()
+ if tty == nil {
+ return "", ErrStatusReport
+ }
+
+ if !o.unsafe {
+ fd := int(tty.Fd()) //nolint:gosec
+ // if in background, we can't control the terminal
+ if !isForeground(fd) {
+ return "", ErrStatusReport
+ }
+
+ t, err := unix.IoctlGetTermios(fd, tcgetattr)
+ if err != nil {
+ return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ }
+ defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck
+
+ noecho := *t
+ noecho.Lflag = noecho.Lflag &^ unix.ECHO
+ noecho.Lflag = noecho.Lflag &^ unix.ICANON
+ if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
+ return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ }
+ }
+
+ // first, send OSC query, which is ignored by terminal which do not support it
+ fmt.Fprintf(tty, OSC+"%d;?"+ST, sequence) //nolint:errcheck
+
+ // then, query cursor position, should be supported by all terminals
+ fmt.Fprintf(tty, CSI+"6n") //nolint:errcheck
+
+ // read the next response
+ res, isOSC, err := o.readNextResponse()
+ if err != nil {
+ return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
+ }
+
+ // if this is not OSC response, then the terminal does not support it
+ if !isOSC {
+ return "", ErrStatusReport
+ }
+
+ // read the cursor query response next and discard the result
+ _, _, err = o.readNextResponse()
+ if err != nil {
+ return "", err
+ }
+
+ // fmt.Println("Rcvd", res[1:])
+ return res, nil
+}
+
+// EnableVirtualTerminalProcessing enables virtual terminal processing on
+// Windows for w and returns a function that restores w to its previous state.
+// On non-Windows platforms, or if w does not refer to a terminal, then it
+// returns a non-nil no-op function and no error.
+func EnableVirtualTerminalProcessing(_ io.Writer) (func() error, error) {
+ return func() error { return nil }, nil
+}
diff --git a/vendor/github.com/muesli/termenv/termenv_windows.go b/vendor/github.com/muesli/termenv/termenv_windows.go
new file mode 100644
index 0000000..f9b1def
--- /dev/null
+++ b/vendor/github.com/muesli/termenv/termenv_windows.go
@@ -0,0 +1,140 @@
+//go:build windows
+// +build windows
+
+package termenv
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+
+ "golang.org/x/sys/windows"
+)
+
+func (o *Output) ColorProfile() Profile {
+ if !o.isTTY() {
+ return Ascii
+ }
+
+ if o.environ.Getenv("ConEmuANSI") == "ON" {
+ return TrueColor
+ }
+
+ winVersion, _, buildNumber := windows.RtlGetNtVersionNumbers()
+ if buildNumber < 10586 || winVersion < 10 {
+ // No ANSI support before Windows 10 build 10586.
+ if o.environ.Getenv("ANSICON") != "" {
+ conVersion := o.environ.Getenv("ANSICON_VER")
+ cv, err := strconv.ParseInt(conVersion, 10, 64)
+ if err != nil || cv < 181 {
+ // No 8 bit color support before v1.81 release.
+ return ANSI
+ }
+
+ return ANSI256
+ }
+
+ return Ascii
+ }
+ if buildNumber < 14931 {
+ // No true color support before build 14931.
+ return ANSI256
+ }
+
+ return TrueColor
+}
+
+func (o Output) foregroundColor() Color {
+ // default gray
+ return ANSIColor(7)
+}
+
+func (o Output) backgroundColor() Color {
+ // default black
+ return ANSIColor(0)
+}
+
+// EnableWindowsANSIConsole enables virtual terminal processing on Windows
+// platforms. This allows the use of ANSI escape sequences in Windows console
+// applications. Ensure this gets called before anything gets rendered with
+// termenv.
+//
+// Returns the original console mode and an error if one occurred.
+func EnableWindowsANSIConsole() (uint32, error) {
+ handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
+ if err != nil {
+ return 0, err
+ }
+
+ var mode uint32
+ err = windows.GetConsoleMode(handle, &mode)
+ if err != nil {
+ return 0, err
+ }
+
+ // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
+ vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
+ return 0, err
+ }
+ }
+
+ return mode, nil
+}
+
+// RestoreWindowsConsole restores the console mode to a previous state.
+func RestoreWindowsConsole(mode uint32) error {
+ handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
+ if err != nil {
+ return err
+ }
+
+ return windows.SetConsoleMode(handle, mode)
+}
+
+// EnableVirtualTerminalProcessing enables virtual terminal processing on
+// Windows for o and returns a function that restores o to its previous state.
+// On non-Windows platforms, or if o does not refer to a terminal, then it
+// returns a non-nil no-op function and no error.
+func EnableVirtualTerminalProcessing(o *Output) (restoreFunc func() error, err error) {
+ // There is nothing to restore until we set the console mode.
+ restoreFunc = func() error {
+ return nil
+ }
+
+ // If o is not a tty, then there is nothing to do.
+ tty, ok := o.Writer().(*os.File)
+ if tty == nil || !ok {
+ return
+ }
+
+ // Get the current console mode. If there is an error, assume that o is not
+ // a terminal, discard the error, and return.
+ var mode uint32
+ if err2 := windows.GetConsoleMode(windows.Handle(tty.Fd()), &mode); err2 != nil {
+ return
+ }
+
+ // If virtual terminal processing is already set, then there is nothing to
+ // do and nothing to restore.
+ if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING == windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
+ return
+ }
+
+ // Enable virtual terminal processing. See
+ // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ if err2 := windows.SetConsoleMode(windows.Handle(tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err2 != nil {
+ err = fmt.Errorf("windows.SetConsoleMode: %w", err2)
+ return
+ }
+
+ // Set the restore function. We maintain a reference to the tty in the
+ // closure (rather than just its handle) to ensure that the tty is not
+ // closed by a finalizer.
+ restoreFunc = func() error {
+ return windows.SetConsoleMode(windows.Handle(tty.Fd()), mode)
+ }
+
+ return
+}