Skip to content
Snippets Groups Projects
Verified Commit 12c7fb3e authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

chore: update packages

parent ff6f3c8b
No related branches found
No related tags found
No related merge requests found
Showing
with 1270 additions and 3 deletions
......@@ -124,6 +124,9 @@ func (c *Client) addOperationStopTextTranslationJobMiddlewares(stack *middleware
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addOpStopTextTranslationJobValidationMiddleware(stack); err != nil {
return err
}
......
......@@ -119,6 +119,9 @@ func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, opt
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addOpTagResourceValidationMiddleware(stack); err != nil {
return err
}
......
......@@ -200,6 +200,9 @@ func (c *Client) addOperationTranslateDocumentMiddlewares(stack *middleware.Stac
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addOpTranslateDocumentValidationMiddleware(stack); err != nil {
return err
}
......
......@@ -182,6 +182,9 @@ func (c *Client) addOperationTranslateTextMiddlewares(stack *middleware.Stack, o
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addOpTranslateTextValidationMiddleware(stack); err != nil {
return err
}
......
......@@ -118,6 +118,9 @@ func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, o
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addOpUntagResourceValidationMiddleware(stack); err != nil {
return err
}
......
......@@ -139,6 +139,9 @@ func (c *Client) addOperationUpdateParallelDataMiddlewares(stack *middleware.Sta
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addCredentialSource(stack, options); err != nil {
return err
}
if err = addIdempotencyToken_opUpdateParallelDataMiddleware(stack, options); err != nil {
return err
}
......
......@@ -40,12 +40,13 @@
"protocol_test.go",
"serializers.go",
"snapshot_test.go",
"sra_operation_order_test.go",
"types/enums.go",
"types/errors.go",
"types/types.go",
"validators.go"
],
"go": "1.15",
"go": "1.22",
"module": "github.com/aws/aws-sdk-go-v2/service/translate",
"unstable": false
}
......@@ -3,4 +3,4 @@
package translate
// goModuleVersion is the tagged release for this module
const goModuleVersion = "1.28.17"
const goModuleVersion = "1.29.2"
......@@ -87,6 +87,7 @@ func New() *Resolver {
var partitionRegexp = struct {
Aws *regexp.Regexp
AwsCn *regexp.Regexp
AwsEusc *regexp.Regexp
AwsIso *regexp.Regexp
AwsIsoB *regexp.Regexp
AwsIsoE *regexp.Regexp
......@@ -96,6 +97,7 @@ var partitionRegexp = struct {
Aws: regexp.MustCompile("^(us|eu|ap|sa|ca|me|af|il|mx)\\-\\w+\\-\\d+$"),
AwsCn: regexp.MustCompile("^cn\\-\\w+\\-\\d+$"),
AwsEusc: regexp.MustCompile("^eusc\\-(de)\\-\\w+\\-\\d+$"),
AwsIso: regexp.MustCompile("^us\\-iso\\-\\w+\\-\\d+$"),
AwsIsoB: regexp.MustCompile("^us\\-isob\\-\\w+\\-\\d+$"),
AwsIsoE: regexp.MustCompile("^eu\\-isoe\\-\\w+\\-\\d+$"),
......@@ -142,39 +144,111 @@ var defaultPartitions = endpoints.Partitions{
endpoints.EndpointKey{
Region: "ap-east-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-east-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-east-1.api.aws",
},
endpoints.EndpointKey{
Region: "ap-northeast-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-northeast-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-northeast-1.api.aws",
},
endpoints.EndpointKey{
Region: "ap-northeast-2",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-northeast-2",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-northeast-2.api.aws",
},
endpoints.EndpointKey{
Region: "ap-south-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-south-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-south-1.api.aws",
},
endpoints.EndpointKey{
Region: "ap-southeast-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-southeast-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-southeast-1.api.aws",
},
endpoints.EndpointKey{
Region: "ap-southeast-2",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ap-southeast-2",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ap-southeast-2.api.aws",
},
endpoints.EndpointKey{
Region: "ca-central-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "ca-central-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.ca-central-1.api.aws",
},
endpoints.EndpointKey{
Region: "eu-central-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "eu-central-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.eu-central-1.api.aws",
},
endpoints.EndpointKey{
Region: "eu-north-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "eu-north-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.eu-north-1.api.aws",
},
endpoints.EndpointKey{
Region: "eu-west-1",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "eu-west-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.eu-west-1.api.aws",
},
endpoints.EndpointKey{
Region: "eu-west-2",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "eu-west-2",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.eu-west-2.api.aws",
},
endpoints.EndpointKey{
Region: "eu-west-3",
}: endpoints.Endpoint{},
endpoints.EndpointKey{
Region: "eu-west-3",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.eu-west-3.api.aws",
},
endpoints.EndpointKey{
Region: "us-east-1",
}: endpoints.Endpoint{},
......@@ -184,6 +258,18 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "translate-fips.us-east-1.amazonaws.com",
},
endpoints.EndpointKey{
Region: "us-east-1",
Variant: endpoints.FIPSVariant | endpoints.DualStackVariant,
}: {
Hostname: "translate-fips.us-east-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-east-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.us-east-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-east-1-fips",
}: endpoints.Endpoint{
......@@ -202,6 +288,18 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "translate-fips.us-east-2.amazonaws.com",
},
endpoints.EndpointKey{
Region: "us-east-2",
Variant: endpoints.FIPSVariant | endpoints.DualStackVariant,
}: {
Hostname: "translate-fips.us-east-2.api.aws",
},
endpoints.EndpointKey{
Region: "us-east-2",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.us-east-2.api.aws",
},
endpoints.EndpointKey{
Region: "us-east-2-fips",
}: endpoints.Endpoint{
......@@ -220,6 +318,18 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "translate-fips.us-west-1.amazonaws.com",
},
endpoints.EndpointKey{
Region: "us-west-1",
Variant: endpoints.FIPSVariant | endpoints.DualStackVariant,
}: {
Hostname: "translate-fips.us-west-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-west-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.us-west-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-west-1-fips",
}: endpoints.Endpoint{
......@@ -238,6 +348,18 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "translate-fips.us-west-2.amazonaws.com",
},
endpoints.EndpointKey{
Region: "us-west-2",
Variant: endpoints.FIPSVariant | endpoints.DualStackVariant,
}: {
Hostname: "translate-fips.us-west-2.api.aws",
},
endpoints.EndpointKey{
Region: "us-west-2",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.us-west-2.api.aws",
},
endpoints.EndpointKey{
Region: "us-west-2-fips",
}: endpoints.Endpoint{
......@@ -284,6 +406,27 @@ var defaultPartitions = endpoints.Partitions{
RegionRegex: partitionRegexp.AwsCn,
IsRegionalized: true,
},
{
ID: "aws-eusc",
Defaults: map[endpoints.DefaultKey]endpoints.Endpoint{
{
Variant: endpoints.FIPSVariant,
}: {
Hostname: "translate-fips.{region}.amazonaws.eu",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
{
Variant: 0,
}: {
Hostname: "translate.{region}.amazonaws.eu",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
RegionRegex: partitionRegexp.AwsEusc,
IsRegionalized: true,
},
{
ID: "aws-iso",
Defaults: map[endpoints.DefaultKey]endpoints.Endpoint{
......@@ -440,6 +583,18 @@ var defaultPartitions = endpoints.Partitions{
}: {
Hostname: "translate-fips.us-gov-west-1.amazonaws.com",
},
endpoints.EndpointKey{
Region: "us-gov-west-1",
Variant: endpoints.FIPSVariant | endpoints.DualStackVariant,
}: {
Hostname: "translate-fips.us-gov-west-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-gov-west-1",
Variant: endpoints.DualStackVariant,
}: {
Hostname: "translate.us-gov-west-1.api.aws",
},
endpoints.EndpointKey{
Region: "us-gov-west-1-fips",
}: endpoints.Endpoint{
......
# Release (2025-02-17)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.22.3
* **Bug Fix**: Fix HTTP metrics data race.
* **Bug Fix**: Replace usages of deprecated ioutil package.
# Release (2025-01-21)
## General Highlights
......
......@@ -3,4 +3,4 @@
package smithy
// goModuleVersion is the tagged release for this module
const goModuleVersion = "1.22.2"
const goModuleVersion = "1.22.3"
version: "2"
run:
tests: false
issues:
include:
- EXC0001
- EXC0005
- EXC0011
- EXC0012
- EXC0013
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- bodyclose
- exhaustive
- goconst
- godot
- godox
- mnd
- gomoddirectives
- goprintffuncname
- gosec
- misspell
- nakedret
- nestif
- nilerr
- noctx
- nolintlint
- prealloc
- revive
- rowserrcheck
- sqlclosecheck
- tparallel
- unconvert
- unparam
- whitespace
- wrapcheck
# disable default linters, they are already enabled in .golangci.yml
disable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
exclusions:
generated: lax
presets:
- common-false-positives
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- gofumpt
- goimports
exclusions:
generated: lax
MIT License
Copyright (c) 2020-2024 Charmbracelet, Inc
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.
# Colorprofile
<p>
<a href="https://github.com/charmbracelet/colorprofile/releases"><img src="https://img.shields.io/github/release/charmbracelet/colorprofile.svg" alt="Latest Release"></a>
<a href="https://pkg.go.dev/github.com/charmbracelet/colorprofile?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/colorprofile?status.svg" alt="GoDoc"></a>
<a href="https://github.com/charmbracelet/colorprofile/actions"><img src="https://github.com/charmbracelet/colorprofile/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
</p>
A simple, powerful—and at times magical—package for detecting terminal color
profiles and performing color (and CSI) degradation.
## Detecting the terminal’s color profile
Detecting the terminal’s color profile is easy.
```go
import "github.com/charmbracelet/colorprofile"
// Detect the color profile. If you’re planning on writing to stderr you'd want
// to use os.Stderr instead.
p := colorprofile.Detect(os.Stdout, os.Environ())
// Comment on the profile.
fmt.Printf("You know, your colors are quite %s.", func() string {
switch p {
case colorprofile.TrueColor:
return "fancy"
case colorprofile.ANSI256:
return "1990s fancy"
case colorprofile.ANSI:
return "normcore"
case colorprofile.Ascii:
return "ancient"
case colorprofile.NoTTY:
return "naughty!"
}
return "...IDK" // this should never happen
}())
```
## Downsampling colors
When necessary, colors can be downsampled to a given profile, or manually
downsampled to a specific profile.
```go
p := colorprofile.Detect(os.Stdout, os.Environ())
c := color.RGBA{0x6b, 0x50, 0xff, 0xff} // #6b50ff
// Downsample to the detected profile, when necessary.
convertedColor := p.Convert(c)
// Or manually convert to a given profile.
ansi256Color := colorprofile.ANSI256.Convert(c)
ansiColor := colorprofile.ANSI.Convert(c)
noColor := colorprofile.Ascii.Convert(c)
noANSI := colorprofile.NoTTY.Convert(c)
```
## Automatic downsampling with a Writer
You can also magically downsample colors in ANSI output, when necessary. If
output is not a TTY ANSI will be dropped entirely.
```go
myFancyANSI := "\x1b[38;2;107;80;255mCute \x1b[1;3mpuppy!!\x1b[m"
// Automatically downsample for the terminal at stdout.
w := colorprofile.NewWriter(os.Stdout, os.Environ())
fmt.Fprintf(w, myFancyANSI)
// Downsample to 4-bit ANSI.
w.Profile = colorprofile.ANSI
fmt.Fprintf(w, myFancyANSI)
// Ascii-fy, no colors.
w.Profile = colorprofile.Ascii
fmt.Fprintf(w, myFancyANSI)
// Strip ANSI altogether.
w.Profile = colorprofile.NoTTY
fmt.Fprintf(w, myFancyANSI) // not as fancy
```
## Feedback
We’d love to hear your thoughts on this project. Feel free to drop us a note!
- [Twitter](https://twitter.com/charmcli)
- [The Fediverse](https://mastodon.social/@charmcli)
- [Discord](https://charm.sh/chat)
## License
[MIT](https://github.com/charmbracelet/bubbletea/raw/master/LICENSE)
---
Part of [Charm](https://charm.sh).
<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة
// Package colorprofile provides a way to downsample ANSI escape sequence
// colors and styles automatically based on output, environment variables, and
// Terminfo databases.
package colorprofile
package colorprofile
import (
"bytes"
"io"
"os/exec"
"runtime"
"strconv"
"strings"
"github.com/charmbracelet/x/term"
"github.com/xo/terminfo"
)
const dumbTerm = "dumb"
// Detect returns the color profile based on the terminal output, and
// environment variables. This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE
// environment variables.
//
// The rules as follows:
// - TERM=dumb is always treated as NoTTY unless CLICOLOR_FORCE=1 is set.
// - If COLORTERM=truecolor, and the profile is not NoTTY, it gest upgraded to TrueColor.
// - Using any 256 color terminal (e.g. TERM=xterm-256color) will set the profile to ANSI256.
// - Using any color terminal (e.g. TERM=xterm-color) will set the profile to ANSI.
// - Using CLICOLOR=1 without TERM defined should be treated as ANSI if the
// output is a terminal.
// - NO_COLOR takes precedence over CLICOLOR/CLICOLOR_FORCE, and will disable
// colors but not text decoration, i.e. bold, italic, faint, etc.
//
// See https://no-color.org/ and https://bixense.com/clicolors/ for more information.
func Detect(output io.Writer, env []string) Profile {
out, ok := output.(term.File)
environ := newEnviron(env)
isatty := isTTYForced(environ) || (ok && term.IsTerminal(out.Fd()))
term, ok := environ.lookup("TERM")
isDumb := !ok || term == dumbTerm
envp := colorProfile(isatty, environ)
if envp == TrueColor || envNoColor(environ) {
// We already know we have TrueColor, or NO_COLOR is set.
return envp
}
if isatty && !isDumb {
tip := Terminfo(term)
tmuxp := tmux(environ)
// Color profile is the maximum of env, terminfo, and tmux.
return max(envp, max(tip, tmuxp))
}
return envp
}
// Env returns the color profile based on the terminal environment variables.
// This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE environment variables.
//
// The rules as follows:
// - TERM=dumb is always treated as NoTTY unless CLICOLOR_FORCE=1 is set.
// - If COLORTERM=truecolor, and the profile is not NoTTY, it gest upgraded to TrueColor.
// - Using any 256 color terminal (e.g. TERM=xterm-256color) will set the profile to ANSI256.
// - Using any color terminal (e.g. TERM=xterm-color) will set the profile to ANSI.
// - Using CLICOLOR=1 without TERM defined should be treated as ANSI if the
// output is a terminal.
// - NO_COLOR takes precedence over CLICOLOR/CLICOLOR_FORCE, and will disable
// colors but not text decoration, i.e. bold, italic, faint, etc.
//
// See https://no-color.org/ and https://bixense.com/clicolors/ for more information.
func Env(env []string) (p Profile) {
return colorProfile(true, newEnviron(env))
}
func colorProfile(isatty bool, env environ) (p Profile) {
term, ok := env.lookup("TERM")
isDumb := (!ok && runtime.GOOS != "windows") || term == dumbTerm
envp := envColorProfile(env)
if !isatty || isDumb {
// Check if the output is a terminal.
// Treat dumb terminals as NoTTY
p = NoTTY
} else {
p = envp
}
if envNoColor(env) && isatty {
if p > Ascii {
p = Ascii
}
return //nolint:nakedret
}
if cliColorForced(env) {
if p < ANSI {
p = ANSI
}
if envp > p {
p = envp
}
return //nolint:nakedret
}
if cliColor(env) {
if isatty && !isDumb && p < ANSI {
p = ANSI
}
}
return p
}
// envNoColor returns true if the environment variables explicitly disable color output
// by setting NO_COLOR (https://no-color.org/).
func envNoColor(env environ) bool {
noColor, _ := strconv.ParseBool(env.get("NO_COLOR"))
return noColor
}
func cliColor(env environ) bool {
cliColor, _ := strconv.ParseBool(env.get("CLICOLOR"))
return cliColor
}
func cliColorForced(env environ) bool {
cliColorForce, _ := strconv.ParseBool(env.get("CLICOLOR_FORCE"))
return cliColorForce
}
func isTTYForced(env environ) bool {
skip, _ := strconv.ParseBool(env.get("TTY_FORCE"))
return skip
}
func colorTerm(env environ) bool {
colorTerm := strings.ToLower(env.get("COLORTERM"))
return colorTerm == "truecolor" || colorTerm == "24bit" ||
colorTerm == "yes" || colorTerm == "true"
}
// envColorProfile returns infers the color profile from the environment.
func envColorProfile(env environ) (p Profile) {
term, ok := env.lookup("TERM")
if !ok || len(term) == 0 || term == dumbTerm {
p = NoTTY
if runtime.GOOS == "windows" {
// Use Windows API to detect color profile. Windows Terminal and
// cmd.exe don't define $TERM.
if wcp, ok := windowsColorProfile(env); ok {
p = wcp
}
}
} else {
p = ANSI
}
parts := strings.Split(term, "-")
switch parts[0] {
case "alacritty",
"contour",
"foot",
"ghostty",
"kitty",
"rio",
"st",
"wezterm":
return TrueColor
case "xterm":
if len(parts) > 1 {
switch parts[1] {
case "ghostty", "kitty":
// These terminals can be defined as xterm-TERMNAME
return TrueColor
}
}
case "tmux", "screen":
if p < ANSI256 {
p = ANSI256
}
}
if isCloudShell, _ := strconv.ParseBool(env.get("GOOGLE_CLOUD_SHELL")); isCloudShell {
return TrueColor
}
// GNU Screen doesn't support TrueColor
// Tmux doesn't support $COLORTERM
if colorTerm(env) && !strings.HasPrefix(term, "screen") && !strings.HasPrefix(term, "tmux") {
return TrueColor
}
if strings.HasSuffix(term, "256color") && p < ANSI256 {
p = ANSI256
}
// Direct color terminals support true colors.
if strings.HasSuffix(term, "direct") {
return TrueColor
}
return //nolint:nakedret
}
// Terminfo returns the color profile based on the terminal's terminfo
// database. This relies on the Tc and RGB capabilities to determine if the
// terminal supports TrueColor.
// If term is empty or "dumb", it returns NoTTY.
func Terminfo(term string) (p Profile) {
if len(term) == 0 || term == "dumb" {
return NoTTY
}
p = ANSI
ti, err := terminfo.Load(term)
if err != nil {
return
}
extbools := ti.ExtBoolCapsShort()
if _, ok := extbools["Tc"]; ok {
return TrueColor
}
if _, ok := extbools["RGB"]; ok {
return TrueColor
}
return
}
// Tmux returns the color profile based on `tmux info` output. Tmux supports
// overriding the terminal's color capabilities, so this function will return
// the color profile based on the tmux configuration.
func Tmux(env []string) Profile {
return tmux(newEnviron(env))
}
// tmux returns the color profile based on the tmux environment variables.
func tmux(env environ) (p Profile) {
if tmux, ok := env.lookup("TMUX"); !ok || len(tmux) == 0 {
// Not in tmux
return NoTTY
}
// Check if tmux has either Tc or RGB capabilities. Otherwise, return
// ANSI256.
p = ANSI256
cmd := exec.Command("tmux", "info")
out, err := cmd.Output()
if err != nil {
return
}
for _, line := range bytes.Split(out, []byte("\n")) {
if (bytes.Contains(line, []byte("Tc")) || bytes.Contains(line, []byte("RGB"))) &&
bytes.Contains(line, []byte("true")) {
return TrueColor
}
}
return
}
// environ is a map of environment variables.
type environ map[string]string
// newEnviron returns a new environment map from a slice of environment
// variables.
func newEnviron(environ []string) environ {
m := make(map[string]string, len(environ))
for _, e := range environ {
parts := strings.SplitN(e, "=", 2)
var value string
if len(parts) == 2 {
value = parts[1]
}
m[parts[0]] = value
}
return m
}
// lookup returns the value of an environment variable and a boolean indicating
// if it exists.
func (e environ) lookup(key string) (string, bool) {
v, ok := e[key]
return v, ok
}
// get returns the value of an environment variable and empty string if it
// doesn't exist.
func (e environ) get(key string) string {
v, _ := e.lookup(key)
return v
}
//go:build !windows
// +build !windows
package colorprofile
func windowsColorProfile(map[string]string) (Profile, bool) {
return 0, false
}
//go:build windows
// +build windows
package colorprofile
import (
"strconv"
"golang.org/x/sys/windows"
)
func windowsColorProfile(env map[string]string) (Profile, bool) {
if env["ConEmuANSI"] == "ON" {
return TrueColor, true
}
if len(env["WT_SESSION"]) > 0 {
// Windows Terminal supports TrueColor
return TrueColor, true
}
major, _, build := windows.RtlGetNtVersionNumbers()
if build < 10586 || major < 10 {
// No ANSI support before WindowsNT 10 build 10586
if len(env["ANSICON"]) > 0 {
ansiconVer := env["ANSICON_VER"]
cv, err := strconv.Atoi(ansiconVer)
if err != nil || cv < 181 {
// No 8 bit color support before ANSICON 1.81
return ANSI, true
}
return ANSI256, true
}
return NoTTY, true
}
if build < 14931 {
// No true color support before build 14931
return ANSI256, true
}
return TrueColor, true
}
package colorprofile
import (
"image/color"
"math"
"github.com/charmbracelet/x/ansi"
"github.com/lucasb-eyer/go-colorful"
)
// Profile is a color profile: NoTTY, Ascii, ANSI, ANSI256, or TrueColor.
type Profile byte
const (
// NoTTY is a profile with no terminal support.
NoTTY Profile = iota
// Ascii is a profile with no color support.
Ascii //nolint:revive
// ANSI is a profile with 16 colors (4-bit).
ANSI
// ANSI256 is a profile with 256 colors (8-bit).
ANSI256
// TrueColor is a profile with 16 million colors (24-bit).
TrueColor
)
// String returns the string representation of a Profile.
func (p Profile) String() string {
switch p {
case TrueColor:
return "TrueColor"
case ANSI256:
return "ANSI256"
case ANSI:
return "ANSI"
case Ascii:
return "Ascii"
case NoTTY:
return "NoTTY"
}
return "Unknown"
}
// Convert transforms a given Color to a Color supported within the Profile.
func (p Profile) Convert(c color.Color) color.Color {
if p <= Ascii {
return nil
}
switch c := c.(type) {
case ansi.BasicColor:
return c
case ansi.ExtendedColor:
if p == ANSI {
return ansi256ToANSIColor(c)
}
return c
case ansi.TrueColor, color.Color:
h, ok := colorful.MakeColor(c)
if !ok {
return nil
}
if p != TrueColor {
ac := hexToANSI256Color(h)
if p == ANSI {
return ansi256ToANSIColor(ac)
}
return ac
}
return c
}
return c
}
func hexToANSI256Color(c colorful.Color) ansi.ExtendedColor {
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 := (cr + cg + cb) / 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 ansi.ExtendedColor(16 + ci) //nolint:gosec
}
return ansi.ExtendedColor(232 + grayIdx) //nolint:gosec
}
func ansi256ToANSIColor(c ansi.ExtendedColor) ansi.BasicColor {
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 ansi.BasicColor(r) //nolint:gosec
}
// 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",
}
package colorprofile
import (
"bytes"
"fmt"
"image/color"
"io"
"strconv"
"github.com/charmbracelet/x/ansi"
)
// NewWriter creates a new color profile writer that downgrades color sequences
// based on the detected color profile.
//
// If environ is nil, it will use os.Environ() to get the environment variables.
//
// It queries the given writer to determine if it supports ANSI escape codes.
// If it does, along with the given environment variables, it will determine
// the appropriate color profile to use for color formatting.
//
// This respects the NO_COLOR, CLICOLOR, and CLICOLOR_FORCE environment variables.
func NewWriter(w io.Writer, environ []string) *Writer {
return &Writer{
Forward: w,
Profile: Detect(w, environ),
}
}
// Writer represents a color profile writer that writes ANSI sequences to the
// underlying writer.
type Writer struct {
Forward io.Writer
Profile Profile
}
// Write writes the given text to the underlying writer.
func (w *Writer) Write(p []byte) (int, error) {
switch w.Profile {
case TrueColor:
return w.Forward.Write(p) //nolint:wrapcheck
case NoTTY:
return io.WriteString(w.Forward, ansi.Strip(string(p))) //nolint:wrapcheck
case Ascii, ANSI, ANSI256:
return w.downsample(p)
default:
return 0, fmt.Errorf("invalid profile: %v", w.Profile)
}
}
// downsample downgrades the given text to the appropriate color profile.
func (w *Writer) downsample(p []byte) (int, error) {
var buf bytes.Buffer
var state byte
parser := ansi.GetParser()
defer ansi.PutParser(parser)
for len(p) > 0 {
parser.Reset()
seq, _, read, newState := ansi.DecodeSequence(p, state, parser)
switch {
case ansi.HasCsiPrefix(seq) && parser.Command() == 'm':
handleSgr(w, parser, &buf)
default:
// If we're not a style SGR sequence, just write the bytes.
if n, err := buf.Write(seq); err != nil {
return n, err //nolint:wrapcheck
}
}
p = p[read:]
state = newState
}
return w.Forward.Write(buf.Bytes()) //nolint:wrapcheck
}
// WriteString writes the given text to the underlying writer.
func (w *Writer) WriteString(s string) (n int, err error) {
return w.Write([]byte(s))
}
func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) {
var style ansi.Style
params := p.Params()
for i := 0; i < len(params); i++ {
param := params[i]
switch param := param.Param(0); param {
case 0:
// SGR default parameter is 0. We use an empty string to reduce the
// number of bytes written to the buffer.
style = append(style, "")
case 30, 31, 32, 33, 34, 35, 36, 37: // 8-bit foreground color
if w.Profile < ANSI {
continue
}
style = style.ForegroundColor(
w.Profile.Convert(ansi.BasicColor(param - 30))) //nolint:gosec
case 38: // 16 or 24-bit foreground color
var c color.Color
if n := ansi.ReadStyleColor(params[i:], &c); n > 0 {
i += n - 1
}
if w.Profile < ANSI {
continue
}
style = style.ForegroundColor(w.Profile.Convert(c))
case 39: // default foreground color
if w.Profile < ANSI {
continue
}
style = style.DefaultForegroundColor()
case 40, 41, 42, 43, 44, 45, 46, 47: // 8-bit background color
if w.Profile < ANSI {
continue
}
style = style.BackgroundColor(
w.Profile.Convert(ansi.BasicColor(param - 40))) //nolint:gosec
case 48: // 16 or 24-bit background color
var c color.Color
if n := ansi.ReadStyleColor(params[i:], &c); n > 0 {
i += n - 1
}
if w.Profile < ANSI {
continue
}
style = style.BackgroundColor(w.Profile.Convert(c))
case 49: // default background color
if w.Profile < ANSI {
continue
}
style = style.DefaultBackgroundColor()
case 58: // 16 or 24-bit underline color
var c color.Color
if n := ansi.ReadStyleColor(params[i:], &c); n > 0 {
i += n - 1
}
if w.Profile < ANSI {
continue
}
style = style.UnderlineColor(w.Profile.Convert(c))
case 59: // default underline color
if w.Profile < ANSI {
continue
}
style = style.DefaultUnderlineColor()
case 90, 91, 92, 93, 94, 95, 96, 97: // 8-bit bright foreground color
if w.Profile < ANSI {
continue
}
style = style.ForegroundColor(
w.Profile.Convert(ansi.BasicColor(param - 90 + 8))) //nolint:gosec
case 100, 101, 102, 103, 104, 105, 106, 107: // 8-bit bright background color
if w.Profile < ANSI {
continue
}
style = style.BackgroundColor(
w.Profile.Convert(ansi.BasicColor(param - 100 + 8))) //nolint:gosec
default:
// If this is not a color attribute, just append it to the style.
style = append(style, strconv.Itoa(param))
}
}
_, _ = buf.WriteString(style.String())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment