pax_global_header 0000666 0000000 0000000 00000000064 14446320525 0014517 g ustar 00root root 0000000 0000000 52 comment=51d72d34e2b9778a31aa5dd79fbdd8cdac50b4d5
termenv-0.15.2/ 0000775 0000000 0000000 00000000000 14446320525 0013264 5 ustar 00root root 0000000 0000000 termenv-0.15.2/.github/ 0000775 0000000 0000000 00000000000 14446320525 0014624 5 ustar 00root root 0000000 0000000 termenv-0.15.2/.github/FUNDING.yml 0000664 0000000 0000000 00000000017 14446320525 0016437 0 ustar 00root root 0000000 0000000 github: muesli
termenv-0.15.2/.github/dependabot.yml 0000664 0000000 0000000 00000000423 14446320525 0017453 0 ustar 00root root 0000000 0000000 version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"
labels:
- "dependencies"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
labels:
- "dependencies"
termenv-0.15.2/.github/workflows/ 0000775 0000000 0000000 00000000000 14446320525 0016661 5 ustar 00root root 0000000 0000000 termenv-0.15.2/.github/workflows/build.yml 0000664 0000000 0000000 00000001176 14446320525 0020510 0 ustar 00root root 0000000 0000000 name: build
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
go-version: [~1.17, ^1]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
GO111MODULE: "on"
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v3
- name: Download Go modules
run: go mod download
- name: Build
run: go build -v ./...
- name: Test
run: go test ./...
if: matrix.platform != 'windows-latest'
termenv-0.15.2/.github/workflows/coverage.yml 0000664 0000000 0000000 00000001321 14446320525 0021174 0 ustar 00root root 0000000 0000000 name: coverage
on: [push, pull_request]
jobs:
coverage:
strategy:
matrix:
go-version: [^1]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
env:
GO111MODULE: "on"
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v3
- name: Coverage
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
go test -race -covermode atomic -coverprofile=profile.cov ./...
GO111MODULE=off go get github.com/mattn/goveralls
$(go env GOPATH)/bin/goveralls -coverprofile=profile.cov -service=github
termenv-0.15.2/.github/workflows/lint-soft.yml 0000664 0000000 0000000 00000001173 14446320525 0021325 0 ustar 00root root 0000000 0000000 name: lint-soft
on:
push:
pull_request:
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
pull-requests: read
jobs:
golangci:
name: lint-soft
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: golangci-lint command line arguments.
args: --config .golangci-soft.yml --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
only-new-issues: true
termenv-0.15.2/.github/workflows/lint.yml 0000664 0000000 0000000 00000001101 14446320525 0020343 0 ustar 00root root 0000000 0000000 name: lint
on:
push:
pull_request:
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: golangci-lint command line arguments.
#args:
# Optional: show only new issues if it's a pull request. The default value is `false`.
only-new-issues: true
termenv-0.15.2/.gitignore 0000664 0000000 0000000 00000000415 14446320525 0015254 0 ustar 00root root 0000000 0000000 # 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/
termenv-0.15.2/.golangci-soft.yml 0000664 0000000 0000000 00000001270 14446320525 0016621 0 ustar 00root root 0000000 0000000 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
- gomnd
- gomoddirectives
- goprintffuncname
- ifshort
# - lll
- misspell
- nakedret
- nestif
- noctx
- nolintlint
- prealloc
- wrapcheck
# disable default linters, they are already enabled in .golangci.yml
disable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
termenv-0.15.2/.golangci.yml 0000664 0000000 0000000 00000000605 14446320525 0015651 0 ustar 00root root 0000000 0000000 run:
tests: false
issues:
include:
- EXC0001
- EXC0005
- EXC0011
- EXC0012
- EXC0013
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- bodyclose
- exportloopref
- goimports
- gosec
- nilerr
- predeclared
- revive
- rowserrcheck
- sqlclosecheck
- tparallel
- unconvert
- unparam
- whitespace
termenv-0.15.2/LICENSE 0000664 0000000 0000000 00000002067 14446320525 0014276 0 ustar 00root root 0000000 0000000 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.
termenv-0.15.2/README.md 0000664 0000000 0000000 00000043555 14446320525 0014557 0 ustar 00root root 0000000 0000000
`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, Windows Terminal
- 8-bit (256): rxvt, screen, xterm, Apple Terminal
- 4-bit (16): Linux Console
### Control Sequences
Click to show feature matrix
| Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) |
| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: |
| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| screen | ⛔[^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.
### System Commands
Click to show feature matrix
| 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 not supported, for more info see [issue#922](https://github.com/alacritty/alacritty/issues/922).
## 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

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)
termenv-0.15.2/ansi_compat.md 0000664 0000000 0000000 00000002121 14446320525 0016077 0 ustar 00root root 0000000 0000000 ## 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\\"
```
termenv-0.15.2/ansicolors.go 0000664 0000000 0000000 00000006537 14446320525 0016002 0 ustar 00root root 0000000 0000000 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",
}
termenv-0.15.2/color.go 0000664 0000000 0000000 00000010447 14446320525 0014737 0 ustar 00root root 0000000 0000000 package termenv
import (
"errors"
"fmt"
"math"
"strings"
"github.com/lucasb-eyer/go-colorful"
)
var (
// ErrInvalidColor gets returned when a color is invalid.
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.
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)
}
return fmt.Sprintf("%d", bgMod(col-8)+90)
}
// 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))
}
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)
}
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)
}
termenv-0.15.2/color_test.go 0000664 0000000 0000000 00000002034 14446320525 0015767 0 ustar 00root root 0000000 0000000 package termenv
import "testing"
func TestXTermColor(t *testing.T) {
var tests = []struct {
input string
color RGBColor
valid bool
}{
{
"\033]11;rgb:fafa/fafa/fafa\033",
RGBColor("#fafafa"),
true,
},
{
"\033]11;rgb:fafa/fafa/fafa\033\\",
RGBColor("#fafafa"),
true,
},
{
"\033]11;rgb:1212/3434/5656\a",
RGBColor("#123456"),
true,
},
{
"\033]11;foo:fafa/fafa/fafaZZ",
"",
false,
},
{
"\033]11;rgb:fafa/fafa",
"",
false,
},
{
"\033]11;rgb:fafa/fafa/fafaY",
"",
false,
},
{
"\033]11;rgb:fafa/fafa/fafaZZ",
"",
false,
},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
color, err := xTermColor(test.input)
if err != nil && test.valid {
t.Fatalf("unexpected error for input %q: %v", test.input, err)
}
if err == nil && !test.valid {
t.Fatalf("expected error for input %v not found", test.input)
}
if color != test.color {
t.Fatalf("wrong color returned, want %v, got %v", test.color, color)
}
})
}
}
termenv-0.15.2/constants_linux.go 0000664 0000000 0000000 00000000155 14446320525 0017047 0 ustar 00root root 0000000 0000000 package termenv
import "golang.org/x/sys/unix"
const (
tcgetattr = unix.TCGETS
tcsetattr = unix.TCSETS
)
termenv-0.15.2/constants_solaris.go 0000664 0000000 0000000 00000000155 14446320525 0017364 0 ustar 00root root 0000000 0000000 package termenv
import "golang.org/x/sys/unix"
const (
tcgetattr = unix.TCGETS
tcsetattr = unix.TCSETS
)
termenv-0.15.2/constants_unix.go 0000664 0000000 0000000 00000000443 14446320525 0016673 0 ustar 00root root 0000000 0000000 //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
)
termenv-0.15.2/copy.go 0000664 0000000 0000000 00000001464 14446320525 0014572 0 ustar 00root root 0000000 0000000 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)
}
termenv-0.15.2/examples/ 0000775 0000000 0000000 00000000000 14446320525 0015102 5 ustar 00root root 0000000 0000000 termenv-0.15.2/examples/color-chart/ 0000775 0000000 0000000 00000000000 14446320525 0017317 5 ustar 00root root 0000000 0000000 termenv-0.15.2/examples/color-chart/color-chart.png 0000664 0000000 0000000 00001310177 14446320525 0022254 0 ustar 00root root 0000000 0000000 PNG
IHDR
o gAMA a cHRM z&