Compare commits
39 Commits
0.13.0-rc1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a079b78de | |||
| 7524a785ce | |||
| 1013f669bb | |||
|
aae20f07cc
|
|||
|
6ef8e1ff52
|
|||
|
7fb9675b1e
|
|||
|
d88b478503
|
|||
|
7a735043cd
|
|||
|
e610f32c35
|
|||
| e04a1e15c4 | |||
|
9d401202b4
|
|||
|
6504be6403
|
|||
| d4944dbf35 | |||
|
8d8d4f799d
|
|||
| 0633f24d1b | |||
|
2e062899c7
|
|||
|
fbd7275f03
|
|||
| cedf185e97 | |||
|
06a57ded02
|
|||
| 6f92ba0deb | |||
| dcd830e3f8 | |||
| 8056703d59 | |||
|
566bdf2bd8
|
|||
|
24288c81d3
|
|||
|
2ef2a7ed2c
|
|||
|
cf8cd7423d
|
|||
| a18f57488f | |||
|
b2e691265a
|
|||
|
bff23f0ae6
|
|||
| 403c7a3e5b | |||
| 66b932a553 | |||
| f64e4b62cf | |||
| e80ecbc332 | |||
| abcbdf57f1 | |||
|
78899f173c
|
|||
| 90142cb783 | |||
|
8dbde3d158
|
|||
| 8f42e36302 | |||
| c2552ec2f6 |
36
.drone.yml
36
.drone.yml
@ -3,7 +3,7 @@ kind: pipeline
|
||||
name: coopcloud.tech/abra
|
||||
steps:
|
||||
- name: make check
|
||||
image: golang:1.24
|
||||
image: golang:1.26
|
||||
commands:
|
||||
- make check
|
||||
|
||||
@ -22,7 +22,7 @@ steps:
|
||||
- tag
|
||||
|
||||
- name: xgettext-go status
|
||||
image: golang:1.24-alpine3.22
|
||||
image: golang:1.26-alpine3.22
|
||||
commands:
|
||||
- apk add patchutils git make
|
||||
- cd /drone/src
|
||||
@ -38,42 +38,14 @@ steps:
|
||||
- tag
|
||||
|
||||
- name: make test
|
||||
image: golang:1.24
|
||||
image: golang:1.26
|
||||
environment:
|
||||
ABRA_DIR: $HOME/.abra
|
||||
CATL_URL: https://git.coopcloud.tech/toolshed/recipes-catalogue-json.git
|
||||
ABRA_DIR: /root/.abra_test
|
||||
commands:
|
||||
- mkdir -p $HOME/.abra
|
||||
- git clone $CATL_URL $HOME/.abra/catalogue
|
||||
- make test
|
||||
depends_on:
|
||||
- make check
|
||||
|
||||
- name: fetch
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags
|
||||
depends_on:
|
||||
- make check
|
||||
- make test
|
||||
when:
|
||||
event: tag
|
||||
|
||||
- name: release
|
||||
image: goreleaser/goreleaser:v2.5.1
|
||||
environment:
|
||||
GITEA_TOKEN:
|
||||
from_secret: goreleaser_gitea_token
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /go
|
||||
commands:
|
||||
- goreleaser release
|
||||
depends_on:
|
||||
- fetch
|
||||
when:
|
||||
event: tag
|
||||
|
||||
- name: publish image
|
||||
image: plugins/docker
|
||||
settings:
|
||||
|
||||
@ -28,6 +28,9 @@ builds:
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
flags:
|
||||
- -v
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- "-X 'main.Commit={{ .Commit }}'"
|
||||
- "-X 'main.Version={{ .Version }}'"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Build image
|
||||
FROM golang:1.24-alpine AS build
|
||||
FROM golang:1.26-alpine AS build
|
||||
|
||||
ENV GOPRIVATE=coopcloud.tech
|
||||
|
||||
@ -15,8 +15,7 @@ WORKDIR /app
|
||||
|
||||
RUN CGO_ENABLED=0 make build
|
||||
|
||||
# Release image ("slim")
|
||||
FROM alpine:3.19.1
|
||||
FROM alpine:3.22
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates \
|
||||
|
||||
10
Makefile
10
Makefile
@ -2,9 +2,10 @@ ABRA := ./cmd/abra
|
||||
XGETTEXT := ./bin/xgettext-go
|
||||
COMMIT := $(shell git rev-list -1 HEAD)
|
||||
GOPATH := $(shell go env GOPATH)
|
||||
GOVERSION := 1.24
|
||||
GOVERSION := 1.26
|
||||
LDFLAGS := "-X 'main.Commit=$(COMMIT)'"
|
||||
DIST_LDFLAGS := $(LDFLAGS)" -s -w"
|
||||
BFLAGS := -v -trimpath
|
||||
GCFLAGS := "all=-l -B"
|
||||
DOMAIN := abra
|
||||
POFILES := $(wildcard pkg/i18n/locales/*.po)
|
||||
@ -22,7 +23,7 @@ install:
|
||||
@go install -gcflags=$(GCFLAGS) -ldflags=$(LDFLAGS) $(ABRA)
|
||||
|
||||
build:
|
||||
@go build -v -gcflags=$(GCFLAGS) -ldflags=$(DIST_LDFLAGS) $(ABRA)
|
||||
@go build $(BFLAGS) -gcflags=$(GCFLAGS) -ldflags=$(DIST_LDFLAGS) $(ABRA)
|
||||
|
||||
build-docker:
|
||||
@docker run -it -v $(PWD):/abra golang:$(GOVERSION) \
|
||||
@ -39,7 +40,7 @@ check:
|
||||
(echo "gofmt: formatting issue - run 'make format' to resolve" && exit 1)
|
||||
|
||||
test:
|
||||
@go test ./... -cover -v
|
||||
@go test ./... -cover -v -p 1
|
||||
|
||||
find-tests:
|
||||
@find . -name "*_test.go"
|
||||
@ -85,3 +86,6 @@ build-mo:
|
||||
for lang in $(POFILES); do \
|
||||
msgfmt $$lang -o $$(echo $$lang | sed 's/.po/.mo/g') --statistics; \
|
||||
done
|
||||
|
||||
release:
|
||||
@goreleaser release --clean
|
||||
|
||||
@ -238,7 +238,7 @@ beforehand. See "abra app backup" for more.`),
|
||||
if upgradeReleaseNotes == "" {
|
||||
upgradeWarnMessages = append(
|
||||
upgradeWarnMessages,
|
||||
fmt.Sprintf("no release notes available for %s", chosenUpgrade),
|
||||
i18n.G("no release notes for upgrading from %s to %s", deployMeta.Version, chosenUpgrade),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +127,7 @@ func DeployOverview(
|
||||
}
|
||||
|
||||
response := false
|
||||
prompt := &survey.Confirm{Message: "proceed?"}
|
||||
prompt := &survey.Confirm{Message: i18n.G("proceed?")}
|
||||
if err := survey.AskOne(prompt, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -97,6 +97,16 @@ your private key and enter your passphrase beforehand.
|
||||
log.Fatal(i18n.G("main app service version for %s is empty?", recipe.Name))
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(recipe.Dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
preCommitHead, err := repo.Head()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
isClean, err := gitPkg.IsClean(recipe.Dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@ -201,11 +211,6 @@ likely to change.
|
||||
}
|
||||
|
||||
if tagString == "" {
|
||||
repo, err := git.PlainOpen(recipe.Dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var lastGitTag tagcmp.Tag
|
||||
iter, err := repo.Tags()
|
||||
if err != nil {
|
||||
@ -282,16 +287,6 @@ likely to change.
|
||||
log.Fatal(i18n.G("invalid version %s specified", tagString))
|
||||
}
|
||||
|
||||
mainService := "app"
|
||||
label := i18n.G("coop-cloud.${STACK_NAME}.version=%s", tagString)
|
||||
if !internal.Dry {
|
||||
if err := recipe.UpdateLabel("compose.y*ml", mainService, label); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
log.Info(i18n.G("dry run: not syncing label %s for recipe %s", tagString, recipe.Name))
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
previousTagLeftHand := strings.Split(tag, "+")[0]
|
||||
newTagStringLeftHand := strings.Split(tagString, "+")[0]
|
||||
@ -300,24 +295,15 @@ likely to change.
|
||||
}
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(recipe.Dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
preCommitHead, err := repo.Head()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil {
|
||||
if cleanErr := cleanTag(recipe, tagString); cleanErr != nil {
|
||||
log.Fatal(cleanErr)
|
||||
log.Fatal(i18n.G("unable to clean up tag after failed release attempt: %s", cleanErr))
|
||||
}
|
||||
if cleanErr := cleanCommit(recipe, preCommitHead); cleanErr != nil {
|
||||
log.Fatal(cleanErr)
|
||||
if resetErr := resetCommit(recipe, preCommitHead); resetErr != nil {
|
||||
log.Fatal(i18n.G("unable to reset commit after failed release attempt: %s", resetErr))
|
||||
}
|
||||
log.Fatal(err)
|
||||
log.Error(err)
|
||||
log.Fatal(i18n.G("release failed. any changes made have been reverted"))
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -375,23 +361,14 @@ func createReleaseFromTag(recipe recipePkg.Recipe, tagString, mainAppVersion str
|
||||
return err
|
||||
}
|
||||
|
||||
tag, err := tagcmp.Parse(tagString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tag.MissingMinor {
|
||||
tag.Minor = "0"
|
||||
tag.MissingMinor = false
|
||||
}
|
||||
|
||||
if tag.MissingPatch {
|
||||
tag.Patch = "0"
|
||||
tag.MissingPatch = false
|
||||
}
|
||||
|
||||
if tagString == "" {
|
||||
tagString = fmt.Sprintf("%s+%s", tag.String(), mainAppVersion)
|
||||
mainService := "app"
|
||||
label := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", tagString)
|
||||
if !internal.Dry {
|
||||
if err := recipe.UpdateLabel("compose.y*ml", mainService, label); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
log.Info(i18n.G("dry run: not syncing label %s for recipe %s", tagString, recipe.Name))
|
||||
}
|
||||
|
||||
if err := addReleaseNotes(recipe, tagString); err != nil {
|
||||
@ -587,9 +564,10 @@ func pushRelease(recipe recipePkg.Recipe, tagString string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// cleanCommit soft removes the latest release commit. No change are lost the
|
||||
// the commit itself is removed. This is the equivalent of `git reset HEAD~1`.
|
||||
func cleanCommit(recipe recipePkg.Recipe, head *plumbing.Reference) error {
|
||||
// resetCommit hard resets to the state before release was started.
|
||||
// This will only remove changes made by the release process due to requiring
|
||||
// a clean working directory.
|
||||
func resetCommit(recipe recipePkg.Recipe, head *plumbing.Reference) error {
|
||||
repo, err := git.PlainOpen(recipe.Dir)
|
||||
if err != nil {
|
||||
return errors.New(i18n.G("unable to open repo in %s: %s", recipe.Dir, err))
|
||||
@ -600,12 +578,12 @@ func cleanCommit(recipe recipePkg.Recipe, head *plumbing.Reference) error {
|
||||
return errors.New(i18n.G("unable to open work tree in %s: %s", recipe.Dir, err))
|
||||
}
|
||||
|
||||
opts := &git.ResetOptions{Commit: head.Hash(), Mode: git.MixedReset}
|
||||
opts := &git.ResetOptions{Commit: head.Hash(), Mode: git.HardReset}
|
||||
if err := worktree.Reset(opts); err != nil {
|
||||
return errors.New(i18n.G("unable to soft reset %s: %s", recipe.Dir, err))
|
||||
return errors.New(i18n.G("unable to hard reset %s: %s", recipe.Dir, err))
|
||||
}
|
||||
|
||||
log.Debug(i18n.G("removed freshly created commit"))
|
||||
log.Debug(i18n.G("reset commit to pre-release state"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
24
cli/run.go
24
cli/run.go
@ -187,28 +187,20 @@ Config:
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(
|
||||
&internal.Debug,
|
||||
"debug",
|
||||
"d",
|
||||
i18n.G("debug"),
|
||||
i18n.G("d"),
|
||||
false,
|
||||
i18n.G("show debug messages"),
|
||||
)
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(
|
||||
&internal.NoInput,
|
||||
"no-input",
|
||||
"n",
|
||||
i18n.G("no-input"),
|
||||
i18n.G("n"),
|
||||
false,
|
||||
i18n.G("toggle non-interactive mode"),
|
||||
)
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(
|
||||
&internal.Offline,
|
||||
"offline",
|
||||
"o",
|
||||
false,
|
||||
i18n.G("prefer offline & filesystem access"),
|
||||
)
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(
|
||||
&internal.Help,
|
||||
i18n.G("help"),
|
||||
@ -217,6 +209,14 @@ Config:
|
||||
i18n.G("help for abra"),
|
||||
)
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(
|
||||
&internal.Offline,
|
||||
i18n.G("offline"),
|
||||
i18n.G("o"),
|
||||
false,
|
||||
i18n.G("prefer offline & filesystem access"),
|
||||
)
|
||||
|
||||
rootCmd.Flags().BoolVarP(
|
||||
&internal.Version,
|
||||
i18n.G("version"),
|
||||
|
||||
106
go.mod
106
go.mod
@ -1,8 +1,6 @@
|
||||
module coopcloud.tech/abra
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.1
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca
|
||||
@ -10,19 +8,19 @@ require (
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||
github.com/charmbracelet/bubbletea v1.3.10
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
github.com/charmbracelet/log v0.4.2
|
||||
github.com/charmbracelet/log v1.0.0
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/cli v28.4.0+incompatible
|
||||
github.com/docker/docker v28.5.2+incompatible
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/go-git/go-git/v5 v5.17.2
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/leonelquinteros/gotext v1.7.2
|
||||
github.com/moby/sys/signal v0.7.1
|
||||
github.com/moby/term v0.5.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/schollz/progressbar/v3 v3.18.0
|
||||
golang.org/x/term v0.35.0
|
||||
github.com/schollz/progressbar/v3 v3.19.0
|
||||
golang.org/x/term v0.41.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.2
|
||||
)
|
||||
@ -30,27 +28,28 @@ require (
|
||||
require (
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.4.1 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.3.2 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.10.2 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.6 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.5.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/go-connections v0.6.0 // indirect
|
||||
@ -61,26 +60,26 @@ require (
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.8.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
||||
github.com/klauspost/compress v1.18.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.21 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
@ -89,7 +88,7 @@ require (
|
||||
github.com/moby/sys/atomicwriter v0.1.0 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/morikuni/aec v1.1.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
@ -100,39 +99,40 @@ require (
|
||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.20.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
|
||||
go.opentelemetry.io/otel v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.8.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/crypto v0.42.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
|
||||
golang.org/x/net v0.44.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/time v0.13.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.42.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/grpc v1.80.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
@ -141,12 +141,12 @@ require (
|
||||
github.com/containers/image v3.0.2+incompatible
|
||||
github.com/containers/storage v1.38.2 // indirect
|
||||
github.com/decentral1se/passgen v1.0.1
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.5 // indirect
|
||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/patternmatcher v0.6.1 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
@ -155,7 +155,9 @@ require (
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/theupdateframework/notary v0.7.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
golang.org/x/sys v0.36.0
|
||||
golang.org/x/sys v0.42.0
|
||||
)
|
||||
|
||||
replace github.com/docker/cli v28.4.0+incompatible => git.coopcloud.tech/toolshed/docker-cli v28.5.3-0.20260202112816-30df2d0b3a00+incompatible
|
||||
|
||||
replace github.com/spf13/cobra => github.com/decentral1se/cobra v1.10.2-i18n
|
||||
|
||||
236
go.sum
236
go.sum
@ -51,8 +51,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
@ -81,8 +81,8 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
|
||||
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
@ -97,7 +97,6 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
@ -137,20 +136,20 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
|
||||
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
|
||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
||||
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
||||
github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
|
||||
github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/log v1.0.0 h1:HVVVMmfOorfj3BA9i8X8UL69Hoz9lI0PYwXfJvOdRc4=
|
||||
github.com/charmbracelet/log v1.0.0/go.mod h1:uYgY3SmLpwJWxmlrPwXvzVYujxis1vAKRV/0VQB7yWA=
|
||||
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
|
||||
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
@ -166,11 +165,13 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
|
||||
github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
|
||||
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
@ -273,8 +274,6 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
|
||||
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
|
||||
github.com/containers/storage v1.38.2 h1:8bAIxnVBGKzMw5EWCivVj24bztQT6IkDp4uHiyhnzwE=
|
||||
github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
@ -300,8 +299,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.5.0 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw=
|
||||
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||
@ -309,13 +308,14 @@ github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjI
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decentral1se/cobra v1.10.2-i18n h1:XR+6AHHfnf4k5NM9f09oLMrEVwz3rkQIAIcqgL8R08g=
|
||||
github.com/decentral1se/cobra v1.10.2-i18n/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/decentral1se/passgen v1.0.1 h1:j2AxK/kHKxDHWZZfkJj8Wgae9+O+DYEqR5sjKthIYKA=
|
||||
github.com/decentral1se/passgen v1.0.1/go.mod h1:530V+lNoPhKtkrX2fIVsIfLhkl47CuiOM7HRgi7C+SU=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
@ -329,8 +329,8 @@ github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r
|
||||
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
|
||||
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
|
||||
github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
@ -389,12 +389,12 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
|
||||
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
|
||||
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
||||
github.com/go-git/go-git/v5 v5.17.2 h1:B+nkdlxdYrvyFK4GPXVU8w1U+YkbsgciIR7f2sZJ104=
|
||||
github.com/go-git/go-git/v5 v5.17.2/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -403,8 +403,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
||||
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@ -425,8 +425,8 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
@ -445,7 +445,6 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -521,17 +520,14 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -546,7 +542,6 @@ github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVU
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
@ -580,8 +575,8 @@ github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVE
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
|
||||
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||
github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY=
|
||||
github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
@ -589,8 +584,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
|
||||
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
@ -614,10 +609,9 @@ github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+
|
||||
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
|
||||
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@ -634,8 +628,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
|
||||
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
|
||||
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
@ -653,7 +647,6 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
@ -662,8 +655,8 @@ github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6U
|
||||
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
|
||||
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
@ -688,8 +681,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ=
|
||||
github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
@ -705,7 +699,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -758,7 +751,6 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
||||
@ -774,7 +766,6 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY
|
||||
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
@ -788,16 +779,13 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
@ -806,9 +794,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@ -821,8 +808,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
|
||||
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
|
||||
github.com/schollz/progressbar/v3 v3.19.0 h1:Ea18xuIRQXLAUidVDox3AbwfUhD0/1IvohyTutOIFoc=
|
||||
github.com/schollz/progressbar/v3 v3.19.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
@ -837,26 +824,17 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
|
||||
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
@ -867,7 +845,6 @@ github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -892,7 +869,6 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D
|
||||
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
@ -921,7 +897,6 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
@ -929,7 +904,6 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
@ -941,37 +915,39 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 h1:vl9obrcoWVKp/lwl8tRE33853I8Xru9HFbw/skNeLs8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0/go.mod h1:GAXRxmLJcVM3u22IjTg74zWBrRCKq8BnOqUVLodpcpw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
|
||||
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
|
||||
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 h1:zWWrB1U6nqhS/k6zYB74CjRpuiitRtLLi68VcgmOEto=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0/go.mod h1:2qXPNBX1OVRC0IwOnfo1ljoid+RD0QK3443EaqVlsOU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
|
||||
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
|
||||
go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo=
|
||||
go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc=
|
||||
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
|
||||
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.8.0 h1:fRAZQDcAFHySxpJ1TwlA1cJ4tvcrw7nXl9xWWC8N5CE=
|
||||
go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@ -990,8 +966,8 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -1002,8 +978,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -1067,8 +1043,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -1164,13 +1140,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1180,16 +1156,16 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -1239,8 +1215,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
@ -1285,10 +1261,10 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@ -1308,8 +1284,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -1323,8 +1299,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=
|
||||
|
||||
@ -10,46 +10,83 @@ import (
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/envfile"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
testPkg "coopcloud.tech/abra/pkg/test"
|
||||
recipePkg "coopcloud.tech/abra/pkg/recipe"
|
||||
"coopcloud.tech/abra/pkg/test"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
expectedAppEnv = envfile.AppEnv{
|
||||
"DOMAIN": test.AppName,
|
||||
"RECIPE": test.RecipeName,
|
||||
}
|
||||
|
||||
expectedApp = appPkg.App{
|
||||
Name: test.AppName,
|
||||
Recipe: recipePkg.Get(expectedAppEnv["RECIPE"]),
|
||||
Domain: expectedAppEnv["DOMAIN"],
|
||||
Env: expectedAppEnv,
|
||||
Path: expectedAppFile.Path,
|
||||
Server: expectedAppFile.Server,
|
||||
}
|
||||
|
||||
expectedAppFile = appPkg.AppFile{
|
||||
Path: test.AppEnvPath,
|
||||
Server: test.ServerName,
|
||||
}
|
||||
|
||||
expectedAppFiles = map[string]appPkg.AppFile{
|
||||
test.AppName: expectedAppFile,
|
||||
}
|
||||
)
|
||||
|
||||
func TestNewApp(t *testing.T) {
|
||||
app, err := appPkg.NewApp(testPkg.ExpectedAppEnv, testPkg.AppName, testPkg.ExpectedAppFile)
|
||||
app, err := appPkg.NewApp(expectedAppEnv, test.AppName, expectedAppFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(app, testPkg.ExpectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, testPkg.ExpectedApp)
|
||||
|
||||
if !reflect.DeepEqual(app, expectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, expectedApp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAppEnvFile(t *testing.T) {
|
||||
app, err := appPkg.ReadAppEnvFile(testPkg.ExpectedAppFile, testPkg.AppName)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
app, err := appPkg.ReadAppEnvFile(expectedAppFile, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(app, testPkg.ExpectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, testPkg.ExpectedApp)
|
||||
|
||||
if !reflect.DeepEqual(app, expectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, expectedApp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetApp(t *testing.T) {
|
||||
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
app, err := appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(app, testPkg.ExpectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, testPkg.ExpectedApp)
|
||||
|
||||
if !reflect.DeepEqual(app, expectedApp) {
|
||||
t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, expectedApp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetComposeFiles(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -94,7 +131,10 @@ func TestGetComposeFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetComposeFilesError(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -186,26 +226,32 @@ func TestFilters(t *testing.T) {
|
||||
|
||||
func compareFilter(t *testing.T, f1 filters.Args, f2 map[string]map[string]bool) {
|
||||
t.Helper()
|
||||
|
||||
j1, err := f1.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
j2, err := json.Marshal(f2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(string(j2), string(j1)); diff != "" {
|
||||
t.Errorf("filters mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteRecipeVersionOverwrite(t *testing.T) {
|
||||
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
app, err := appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer t.Cleanup(func() {
|
||||
t.Cleanup(func() {
|
||||
if err := app.WipeRecipeVersion(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -217,7 +263,7 @@ func TestWriteRecipeVersionOverwrite(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
app, err = appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
app, err = appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -226,7 +272,10 @@ func TestWriteRecipeVersionOverwrite(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWriteRecipeVersionUnknown(t *testing.T) {
|
||||
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
app, err := appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
appPkg "coopcloud.tech/abra/pkg/app"
|
||||
"coopcloud.tech/abra/pkg/test"
|
||||
testPkg "coopcloud.tech/abra/pkg/test"
|
||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||
|
||||
@ -11,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
func TestGetTimeoutFromLabel(t *testing.T) {
|
||||
testPkg.MkServerAppRecipe()
|
||||
defer testPkg.RmServerAppRecipe()
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
tests := []struct {
|
||||
configuredTimeout string
|
||||
@ -25,7 +26,7 @@ func TestGetTimeoutFromLabel(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
app, err := appPkg.GetApp(expectedAppFiles, testPkg.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -10,8 +10,9 @@ import (
|
||||
func TestFindAbraConfig(t *testing.T) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
Dir string
|
||||
Config string
|
||||
@ -51,8 +52,9 @@ func TestFindAbraConfig(t *testing.T) {
|
||||
func TestLoadAbraConfigGetAbraDir(t *testing.T) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Setenv("ABRA_DIR", "")
|
||||
|
||||
t.Run("default", func(t *testing.T) {
|
||||
@ -67,7 +69,7 @@ func TestLoadAbraConfigGetAbraDir(t *testing.T) {
|
||||
t.Cleanup(func() { os.Chdir(wd) })
|
||||
err = os.Chdir(filepath.Join(wd, "testdata/abraconfig1"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := LoadAbraConfig()
|
||||
@ -81,7 +83,7 @@ func TestLoadAbraConfigGetAbraDir(t *testing.T) {
|
||||
t.Cleanup(func() { os.Chdir(wd) })
|
||||
err := os.Chdir(filepath.Join(wd, "testdata/abraconfig2"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := LoadAbraConfig()
|
||||
@ -104,8 +106,9 @@ func TestLoadAbraConfigGetAbraDir(t *testing.T) {
|
||||
func TestLoadAbraConfigServersDir(t *testing.T) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Setenv("ABRA_DIR", "")
|
||||
|
||||
t.Run("default", func(t *testing.T) {
|
||||
@ -120,7 +123,7 @@ func TestLoadAbraConfigServersDir(t *testing.T) {
|
||||
t.Cleanup(func() { os.Chdir(wd) })
|
||||
err = os.Chdir(filepath.Join(wd, "testdata/abraconfig1"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := LoadAbraConfig()
|
||||
|
||||
@ -10,48 +10,73 @@ import (
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/envfile"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
testPkg "coopcloud.tech/abra/pkg/test"
|
||||
"coopcloud.tech/abra/pkg/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
expectedAppEnv = envfile.AppEnv{
|
||||
"DOMAIN": test.AppName,
|
||||
"RECIPE": test.RecipeName,
|
||||
}
|
||||
|
||||
expectedAppFile = appPkg.AppFile{
|
||||
Path: test.AppEnvPath,
|
||||
Server: test.ServerName,
|
||||
}
|
||||
|
||||
expectedAppFiles = map[string]appPkg.AppFile{
|
||||
test.AppName: expectedAppFile,
|
||||
}
|
||||
)
|
||||
|
||||
func TestGetAllFoldersInDirectory(t *testing.T) {
|
||||
folders, err := config.GetAllFoldersInDirectory(testPkg.TestDir)
|
||||
folders, err := config.GetAllFoldersInDirectory(test.TestDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(folders, testPkg.TFolders) {
|
||||
t.Fatalf("did not get expected folders. Expected: (%s), Got: (%s)", strings.Join(testPkg.TFolders, ","), strings.Join(folders, ","))
|
||||
|
||||
if !reflect.DeepEqual(folders, test.TFolders) {
|
||||
t.Fatalf("did not get expected folders. Expected: (%s), Got: (%s)", strings.Join(test.TFolders, ","), strings.Join(folders, ","))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllFilesInDirectory(t *testing.T) {
|
||||
files, err := config.GetAllFilesInDirectory(testPkg.TestDir)
|
||||
files, err := config.GetAllFilesInDirectory(test.TestDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var fileNames []string
|
||||
for _, file := range files {
|
||||
fileNames = append(fileNames, file.Name())
|
||||
}
|
||||
if !reflect.DeepEqual(fileNames, testPkg.TFiles) {
|
||||
t.Fatalf("did not get expected files. Expected: (%s), Got: (%s)", strings.Join(testPkg.TFiles, ","), strings.Join(fileNames, ","))
|
||||
|
||||
if !reflect.DeepEqual(fileNames, test.TFiles) {
|
||||
t.Fatalf("did not get expected files. Expected: (%s), Got: (%s)", strings.Join(test.TFiles, ","), strings.Join(fileNames, ","))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadEnv(t *testing.T) {
|
||||
env, err := envfile.ReadEnv(testPkg.ExpectedAppFile.Path)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
env, err := envfile.ReadEnv(expectedAppFile.Path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(env, testPkg.ExpectedAppEnv) {
|
||||
|
||||
if !reflect.DeepEqual(env, expectedAppEnv) {
|
||||
t.Fatal("did not get expected application settings")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAbraShEnvVars(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -78,9 +103,11 @@ func TestReadAbraShEnvVars(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadAbraShCmdNames(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -102,9 +129,11 @@ func TestReadAbraShCmdNames(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckEnv(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -135,9 +164,11 @@ func TestCheckEnv(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckEnvError(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -170,9 +201,11 @@ func TestCheckEnvError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEnvVarCommentsRemoved(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -201,9 +234,11 @@ func TestEnvVarCommentsRemoved(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEnvVarModifiersIncluded(t *testing.T) {
|
||||
r := recipe.Get("abra-test-recipe")
|
||||
err := r.EnsureExists()
|
||||
if err != nil {
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := recipe.Get(test.AbraTestRecipe)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -225,7 +260,10 @@ func TestEnvVarModifiersIncluded(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNoOverwriteNonVersionEnvVars(t *testing.T) {
|
||||
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
app, err := appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -234,7 +272,7 @@ func TestNoOverwriteNonVersionEnvVars(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
app, err = appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||
app, err = appPkg.GetApp(expectedAppFiles, test.AppName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -8,11 +8,44 @@ import (
|
||||
"testing"
|
||||
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/log"
|
||||
)
|
||||
|
||||
func setup() {
|
||||
teardown()
|
||||
|
||||
if err := os.Mkdir(os.ExpandEnv("$ABRA_DIR"), 0764); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Mkdir(os.ExpandEnv("$ABRA_DIR/recipes"), 0764); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
abraDir := os.ExpandEnv("$ABRA_DIR")
|
||||
if abraDir == fmt.Sprintf("%s/.abra", os.ExpandEnv("$HOME")) {
|
||||
log.Fatal("set $ABRA_DIR before running the test suite")
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(abraDir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
setup()
|
||||
t.Cleanup(func() { teardown() })
|
||||
|
||||
dir := path.Join(config.RECIPES_DIR, "gitea")
|
||||
os.RemoveAll(dir)
|
||||
if err := os.RemoveAll(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
gitURL := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, "gitea")
|
||||
if err := Clone(dir, gitURL); err != nil {
|
||||
@ -25,6 +58,11 @@ func TestClone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelGitClone(t *testing.T) {
|
||||
t.Skip("https://git.coopcloud.tech/toolshed/abra/issues/814")
|
||||
|
||||
setup()
|
||||
t.Cleanup(func() { teardown() })
|
||||
|
||||
dir := path.Join(config.RECIPES_DIR, "gitea")
|
||||
os.RemoveAll(dir)
|
||||
|
||||
|
||||
@ -23,6 +23,14 @@ var (
|
||||
GC = Mo.GetC
|
||||
)
|
||||
|
||||
func GetLocaleStr() string {
|
||||
locale := os.Getenv("LANG")
|
||||
if lastUnderscore := strings.LastIndex(locale, "_"); lastUnderscore != -1 {
|
||||
locale = locale[0:lastUnderscore]
|
||||
}
|
||||
return locale
|
||||
}
|
||||
|
||||
func LoadLocale() (string, *gotext.Mo) {
|
||||
entries, err := assetFS.ReadDir("locales")
|
||||
if err != nil {
|
||||
@ -38,11 +46,7 @@ func LoadLocale() (string, *gotext.Mo) {
|
||||
}
|
||||
}
|
||||
|
||||
locale := os.Getenv("LANG")
|
||||
if lastUnderscore := strings.LastIndex(locale, "_"); lastUnderscore != -1 {
|
||||
locale = locale[0:lastUnderscore]
|
||||
}
|
||||
|
||||
locale := GetLocaleStr()
|
||||
if locale != "" {
|
||||
if slices.Contains(linguas, locale) {
|
||||
Locale = locale
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||
"POT-Creation-Date: 2026-02-16 12:06+0100\n"
|
||||
"POT-Creation-Date: 2026-04-11 11:34+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -204,7 +204,7 @@ msgstr ""
|
||||
msgid "%s OVERVIEW"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/server/add.go:127 ./pkg/secret/secret.go:235 ./pkg/secret/secret.go:255 ./pkg/server/server.go:21
|
||||
#: ./cli/server/add.go:127 ./pkg/secret/secret.go:303 ./pkg/secret/secret.go:326 ./pkg/server/server.go:21
|
||||
#, c-format
|
||||
msgid "%s already exists"
|
||||
msgstr ""
|
||||
@ -384,7 +384,7 @@ msgstr ""
|
||||
msgid "%s not considered semver-like"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:135
|
||||
#: ./pkg/secret/secret.go:156
|
||||
#, c-format
|
||||
msgid "%s not enabled in recipe config, skipping"
|
||||
msgstr ""
|
||||
@ -449,7 +449,7 @@ msgstr ""
|
||||
msgid "%s was successfully moved from %s to %s 🎉"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:299
|
||||
#: ./cli/recipe/release.go:294
|
||||
#, c-format
|
||||
msgid "%s+... conflicts with a previous release: %s"
|
||||
msgstr ""
|
||||
@ -1109,7 +1109,7 @@ msgstr ""
|
||||
msgid "ON SERVER"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:176
|
||||
#: ./cli/recipe/release.go:186
|
||||
msgid "PROPOSED CHANGES"
|
||||
msgstr ""
|
||||
|
||||
@ -1273,7 +1273,7 @@ msgstr ""
|
||||
msgid "SERVER"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/ps.go:185 ./cli/recipe/release.go:176 ./cli/recipe/version.go:69 ./cli/recipe/version.go:110
|
||||
#: ./cli/app/ps.go:185 ./cli/recipe/release.go:186 ./cli/recipe/version.go:69 ./cli/recipe/version.go:110
|
||||
msgid "SERVICE"
|
||||
msgstr ""
|
||||
|
||||
@ -1594,7 +1594,7 @@ msgstr ""
|
||||
msgid "[hijack] end of stdout"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:128
|
||||
#: ./cli/recipe/release.go:138
|
||||
#, c-format
|
||||
msgid "\n"
|
||||
"The following options are two types of initial semantic version that you can\n"
|
||||
@ -1747,7 +1747,7 @@ msgstr ""
|
||||
msgid "add [[server] | --local] [flags]"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:495
|
||||
#: ./cli/recipe/release.go:472
|
||||
msgid "add release note? (leave empty to skip)"
|
||||
msgstr ""
|
||||
|
||||
@ -1807,7 +1807,7 @@ msgstr ""
|
||||
msgid "app domain %s (%s) does not appear to resolve to app server %s (%s)?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:363
|
||||
#: ./cli/recipe/release.go:349
|
||||
msgid "app service is missing image tag?"
|
||||
msgstr ""
|
||||
|
||||
@ -1825,7 +1825,7 @@ msgstr ""
|
||||
msgid "attempting to create client for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:224
|
||||
#: ./pkg/secret/secret.go:281
|
||||
#, c-format
|
||||
msgid "attempting to generate and store %s on %s"
|
||||
msgstr ""
|
||||
@ -1982,7 +1982,7 @@ msgstr ""
|
||||
msgid "cannot resolve ipv4 for %s?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:120
|
||||
#: ./cli/recipe/release.go:130
|
||||
msgid "cannot specify tag and bump type at the same time"
|
||||
msgstr ""
|
||||
|
||||
@ -2058,6 +2058,11 @@ msgstr ""
|
||||
msgid "chaos"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:235
|
||||
#, c-format
|
||||
msgid "charset=bytes only supports encoding=base64, got encoding=%s for secret %s, defaulting to base64"
|
||||
msgstr ""
|
||||
|
||||
#. translators: `app check` command
|
||||
#: ./cli/app/check.go:23
|
||||
msgid "check <domain> [flags]"
|
||||
@ -2079,7 +2084,7 @@ msgstr ""
|
||||
msgid "choosing %s as latest version of %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:277
|
||||
#: ./cli/recipe/release.go:282
|
||||
#, c-format
|
||||
msgid "choosing %s as new version for %s"
|
||||
msgstr ""
|
||||
@ -2094,7 +2099,7 @@ msgstr ""
|
||||
msgid "choosing %s as version to upgrade"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:427
|
||||
#: ./cli/recipe/release.go:404
|
||||
#, c-format
|
||||
msgid "chore: publish %s release"
|
||||
msgstr ""
|
||||
@ -2253,7 +2258,7 @@ msgstr ""
|
||||
msgid "context lacks Docker endpoint"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:286 ./pkg/recipe/compose.go:229
|
||||
#: ./pkg/recipe/compose.go:229
|
||||
#, c-format
|
||||
msgid "coop-cloud.${STACK_NAME}.version=%s"
|
||||
msgstr ""
|
||||
@ -2317,7 +2322,7 @@ msgstr ""
|
||||
msgid "created secret on %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:565
|
||||
#: ./cli/recipe/release.go:542
|
||||
#, c-format
|
||||
msgid "created tag %s at %s"
|
||||
msgstr ""
|
||||
@ -2382,10 +2387,14 @@ msgstr ""
|
||||
#. no spaces in between
|
||||
#. translators: `abra recipe diff` aliases. use a comma separated list of aliases
|
||||
#. with no spaces in between
|
||||
#: ./cli/app/backup.go:73 ./cli/app/deploy.go:30 ./cli/recipe/diff.go:16
|
||||
#: ./cli/app/backup.go:73 ./cli/app/deploy.go:30 ./cli/recipe/diff.go:16 ./cli/run.go:191
|
||||
msgid "d"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:190
|
||||
msgid "debug"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/secret.go:326
|
||||
#, c-format
|
||||
msgid "deleted %s successfully from local pass store"
|
||||
@ -2561,7 +2570,7 @@ msgstr ""
|
||||
msgid "dry run: adding %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:455
|
||||
#: ./cli/recipe/release.go:432
|
||||
#, c-format
|
||||
msgid "dry run: move release note from 'next' to %s"
|
||||
msgstr ""
|
||||
@ -2570,11 +2579,11 @@ msgstr ""
|
||||
msgid "dry run: no changes commited"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:520
|
||||
#: ./cli/recipe/release.go:497
|
||||
msgid "dry run: no changes committed"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/catalogue/catalogue.go:271 ./cli/recipe/release.go:572
|
||||
#: ./cli/catalogue/catalogue.go:271 ./cli/recipe/release.go:549
|
||||
msgid "dry run: no changes published"
|
||||
msgstr ""
|
||||
|
||||
@ -2583,12 +2592,12 @@ msgstr ""
|
||||
msgid "dry run: no git changes pushed in %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:545
|
||||
#: ./cli/recipe/release.go:522
|
||||
#, c-format
|
||||
msgid "dry run: no git tag created (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:292
|
||||
#: ./cli/recipe/release.go:371
|
||||
#, c-format
|
||||
msgid "dry run: not syncing label %s for recipe %s"
|
||||
msgstr ""
|
||||
@ -2598,7 +2607,7 @@ msgstr ""
|
||||
msgid "dry run: remote %s (%s) not created"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/move.go:349 ./cli/catalogue/catalogue.go:301 ./cli/recipe/release.go:645
|
||||
#: ./cli/app/move.go:349 ./cli/catalogue/catalogue.go:301 ./cli/recipe/release.go:623
|
||||
msgid "dry-run"
|
||||
msgstr ""
|
||||
|
||||
@ -2732,7 +2741,7 @@ msgstr ""
|
||||
msgid "f"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:398
|
||||
#: ./cli/recipe/release.go:375
|
||||
#, c-format
|
||||
msgid "failed to add release notes: %s"
|
||||
msgstr ""
|
||||
@ -2752,7 +2761,7 @@ msgstr ""
|
||||
msgid "failed to check out %s in %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:402
|
||||
#: ./cli/recipe/release.go:379
|
||||
#, c-format
|
||||
msgid "failed to commit changes: %s"
|
||||
msgstr ""
|
||||
@ -2792,6 +2801,11 @@ msgstr ""
|
||||
msgid "failed to create volume %s on %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:104
|
||||
#, c-format
|
||||
msgid "failed to generate random bytes: %w"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/recipe/git.go:421
|
||||
#, c-format
|
||||
msgid "failed to get compose config for %s: %s"
|
||||
@ -2835,7 +2849,7 @@ msgstr ""
|
||||
msgid "failed to parse image for %s in %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:410
|
||||
#: ./cli/recipe/release.go:387
|
||||
#, c-format
|
||||
msgid "failed to publish new release: %s"
|
||||
msgstr ""
|
||||
@ -2904,7 +2918,7 @@ msgstr ""
|
||||
msgid "failed to store secret on %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:406
|
||||
#: ./cli/recipe/release.go:383
|
||||
#, c-format
|
||||
msgid "failed to tag release: %s"
|
||||
msgstr ""
|
||||
@ -3013,12 +3027,12 @@ msgstr ""
|
||||
msgid "generate all secrets"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:67 ./pkg/secret/secret.go:85
|
||||
#: ./pkg/secret/secret.go:77 ./pkg/secret/secret.go:95
|
||||
#, c-format
|
||||
msgid "generated %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:280
|
||||
#: ./pkg/secret/secret.go:351
|
||||
#, c-format
|
||||
msgid "generated and stored %v on %s"
|
||||
msgstr ""
|
||||
@ -3141,7 +3155,7 @@ msgstr ""
|
||||
msgid "git: opening repository in %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:215
|
||||
#: ./cli/run.go:207
|
||||
msgid "h"
|
||||
msgstr ""
|
||||
|
||||
@ -3161,7 +3175,7 @@ msgstr ""
|
||||
msgid "healthcheck enabled for all services"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:214
|
||||
#: ./cli/run.go:206
|
||||
msgid "help"
|
||||
msgstr ""
|
||||
|
||||
@ -3169,7 +3183,7 @@ msgstr ""
|
||||
msgid "help [command]"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:217
|
||||
#: ./cli/run.go:209
|
||||
msgid "help for abra"
|
||||
msgstr ""
|
||||
|
||||
@ -3277,15 +3291,15 @@ msgstr ""
|
||||
msgid "including VOLUMES=%v in backupbot exec invocation"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:656 ./cli/recipe/upgrade.go:378
|
||||
#: ./cli/recipe/release.go:634 ./cli/recipe/upgrade.go:378
|
||||
msgid "increase the major part of the version"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:664 ./cli/recipe/upgrade.go:386
|
||||
#: ./cli/recipe/release.go:642 ./cli/recipe/upgrade.go:386
|
||||
msgid "increase the minor part of the version"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:672 ./cli/recipe/upgrade.go:394
|
||||
#: ./cli/recipe/release.go:650 ./cli/recipe/upgrade.go:394
|
||||
msgid "increase the patch part of the version"
|
||||
msgstr ""
|
||||
|
||||
@ -3377,7 +3391,7 @@ msgstr ""
|
||||
msgid "invalid tmpfs source, source must be empty"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:282
|
||||
#: ./cli/recipe/release.go:287
|
||||
#, c-format
|
||||
msgid "invalid version %s specified"
|
||||
msgstr ""
|
||||
@ -3533,7 +3547,7 @@ msgstr ""
|
||||
msgid "main app service version for %s is empty?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:66 ./cli/internal/recipe.go:80 ./cli/recipe/release.go:653 ./cli/recipe/upgrade.go:375
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:66 ./cli/internal/recipe.go:80 ./cli/recipe/release.go:631 ./cli/recipe/upgrade.go:375
|
||||
msgid "major"
|
||||
msgstr ""
|
||||
|
||||
@ -3562,7 +3576,7 @@ msgstr ""
|
||||
msgid "migrating app config from %s to %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:68 ./cli/internal/recipe.go:82 ./cli/recipe/release.go:661 ./cli/recipe/upgrade.go:383
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:68 ./cli/internal/recipe.go:82 ./cli/recipe/release.go:639 ./cli/recipe/upgrade.go:383
|
||||
msgid "minor"
|
||||
msgstr ""
|
||||
|
||||
@ -3582,7 +3596,7 @@ msgstr ""
|
||||
msgid "missing arguments [secret]/[version] or '--all'"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:131
|
||||
#: ./pkg/secret/secret.go:152
|
||||
#, c-format
|
||||
msgid "missing version for secret? (%s)"
|
||||
msgstr ""
|
||||
@ -3605,7 +3619,7 @@ msgstr ""
|
||||
#. no spaces in between
|
||||
#. translators: `abra recipe new` aliases. use a comma separated list of
|
||||
#. aliases with no spaces in between
|
||||
#: ./cli/app/new.go:48 ./cli/recipe/new.go:36
|
||||
#: ./cli/app/new.go:48 ./cli/recipe/new.go:36 ./cli/run.go:199
|
||||
msgid "n"
|
||||
msgstr ""
|
||||
|
||||
@ -3661,7 +3675,7 @@ msgstr ""
|
||||
msgid "new recipe '%s' created: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:585
|
||||
#: ./cli/recipe/release.go:562
|
||||
#, c-format
|
||||
msgid "new release published: %s"
|
||||
msgstr ""
|
||||
@ -3712,7 +3726,7 @@ msgstr ""
|
||||
msgid "no backupbot discovered, is it deployed?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/catalogue/catalogue.go:231 ./cli/recipe/release.go:531
|
||||
#: ./cli/catalogue/catalogue.go:231 ./cli/recipe/release.go:508
|
||||
#, c-format
|
||||
msgid "no changes discovered in %s, nothing to publish?"
|
||||
msgstr ""
|
||||
@ -3746,7 +3760,7 @@ msgstr ""
|
||||
msgid "no existing label found, automagic insertion not supported yet"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:124
|
||||
#: ./cli/recipe/release.go:134
|
||||
#, c-format
|
||||
msgid "no git tags found for %s"
|
||||
msgstr ""
|
||||
@ -3765,6 +3779,11 @@ msgstr ""
|
||||
msgid "no recipe name provided"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/upgrade.go:241
|
||||
#, c-format
|
||||
msgid "no release notes for upgrading from %s to %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/secret.go:234
|
||||
#, c-format
|
||||
msgid "no secret %s available for recipe %s?"
|
||||
@ -3857,6 +3876,10 @@ msgstr ""
|
||||
msgid "no-domain-checks"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:198
|
||||
msgid "no-input"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/run.go:109
|
||||
msgid "no-tty"
|
||||
msgstr ""
|
||||
@ -3866,7 +3889,7 @@ msgstr ""
|
||||
msgid "not enough arguments: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:124
|
||||
#: ./pkg/secret/secret.go:145
|
||||
msgid "not generating app secrets, none enabled in recipe config"
|
||||
msgstr ""
|
||||
|
||||
@ -3893,6 +3916,14 @@ msgstr ""
|
||||
msgid "number of retry attempts"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:215
|
||||
msgid "o"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:214
|
||||
msgid "offline"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/cp.go:91
|
||||
msgid "one of <src>/<dest> arguments must take $SERVICE:$PATH form"
|
||||
msgstr ""
|
||||
@ -3968,7 +3999,7 @@ msgstr ""
|
||||
msgid "pass command not found on $PATH, is it installed?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:70 ./cli/internal/recipe.go:84 ./cli/recipe/release.go:669 ./cli/recipe/upgrade.go:391
|
||||
#: ./cli/internal/recipe.go:48 ./cli/internal/recipe.go:70 ./cli/internal/recipe.go:84 ./cli/recipe/release.go:647 ./cli/recipe/upgrade.go:391
|
||||
msgid "patch"
|
||||
msgstr ""
|
||||
|
||||
@ -4018,7 +4049,7 @@ msgstr ""
|
||||
msgid "polling undeploy status"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/run.go:209
|
||||
#: ./cli/run.go:217
|
||||
msgid "prefer offline & filesystem access"
|
||||
msgstr ""
|
||||
|
||||
@ -4026,7 +4057,7 @@ msgstr ""
|
||||
msgid "print machine-readable output"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/internal/deploy.go:231
|
||||
#: ./cli/internal/deploy.go:130 ./cli/internal/deploy.go:231
|
||||
msgid "proceed?"
|
||||
msgstr ""
|
||||
|
||||
@ -4088,7 +4119,7 @@ msgstr ""
|
||||
#. with no spaces in between
|
||||
#. translators: `abra recipe` aliases. use a comma separated list of aliases
|
||||
#. with no spaces in between
|
||||
#: ./cli/app/backup.go:327 ./cli/app/list.go:304 ./cli/app/move.go:350 ./cli/app/run.go:23 ./cli/app/upgrade.go:486 ./cli/catalogue/catalogue.go:302 ./cli/recipe/recipe.go:12 ./cli/recipe/release.go:646
|
||||
#: ./cli/app/backup.go:327 ./cli/app/list.go:304 ./cli/app/move.go:350 ./cli/app/run.go:23 ./cli/app/upgrade.go:486 ./cli/catalogue/catalogue.go:302 ./cli/recipe/recipe.go:12 ./cli/recipe/release.go:624
|
||||
msgid "r"
|
||||
msgstr ""
|
||||
|
||||
@ -4204,6 +4235,10 @@ msgstr ""
|
||||
msgid "release <recipe> [version] [flags]"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:306
|
||||
msgid "release failed. any changes made have been reverted"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/upgrade.go:485
|
||||
msgid "releasenotes"
|
||||
msgstr ""
|
||||
@ -4264,11 +4299,7 @@ msgstr ""
|
||||
msgid "removed dirty suffix from .env version: %s -> %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:608
|
||||
msgid "removed freshly created commit"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:626
|
||||
#: ./cli/recipe/release.go:604
|
||||
#, c-format
|
||||
msgid "removed freshly created tag %s"
|
||||
msgstr ""
|
||||
@ -4340,7 +4371,7 @@ msgstr ""
|
||||
msgid "repo set config: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/move.go:352 ./cli/catalogue/catalogue.go:304 ./cli/recipe/release.go:648
|
||||
#: ./cli/app/move.go:352 ./cli/catalogue/catalogue.go:304 ./cli/recipe/release.go:626
|
||||
msgid "report changes that would be made"
|
||||
msgstr ""
|
||||
|
||||
@ -4361,6 +4392,10 @@ msgstr ""
|
||||
msgid "reset <recipe> [flags]"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:586
|
||||
msgid "reset commit to pre-release state"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/lint.go:45
|
||||
msgid "resolve"
|
||||
msgstr ""
|
||||
@ -4567,7 +4602,7 @@ msgstr ""
|
||||
msgid "searching abra.sh for version for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:149
|
||||
#: ./pkg/secret/secret.go:170
|
||||
#, c-format
|
||||
msgid "secret %s is > %d chars when combined with %s"
|
||||
msgstr ""
|
||||
@ -4820,7 +4855,7 @@ msgstr ""
|
||||
msgid "skipping domain checks, no DOMAIN=... configured"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/secret/secret.go:219
|
||||
#: ./pkg/secret/secret.go:276
|
||||
#, c-format
|
||||
msgid "skipping generation of %s (generate=false)"
|
||||
msgstr ""
|
||||
@ -4905,7 +4940,7 @@ msgstr ""
|
||||
msgid "ssh url: %s, "
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:577
|
||||
#: ./cli/recipe/release.go:554
|
||||
msgid "ssh-agent not found. see \"abra recipe release --help\" and try again"
|
||||
msgstr ""
|
||||
|
||||
@ -4985,7 +5020,7 @@ msgstr ""
|
||||
msgid "tag all images with stable tags"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:218
|
||||
#: ./cli/recipe/release.go:223
|
||||
#, c-format
|
||||
msgid "tag at commit %s is unannotated or otherwise broken"
|
||||
msgstr ""
|
||||
@ -5118,6 +5153,11 @@ msgstr ""
|
||||
msgid "unable to clean up git clone of %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:300
|
||||
#, c-format
|
||||
msgid "unable to clean up tag after failed release attempt: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/list.go:152
|
||||
#, c-format
|
||||
msgid "unable to clone %s: %s"
|
||||
@ -5128,7 +5168,7 @@ msgstr ""
|
||||
msgid "unable to connect to %s, please check your SSH config"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:126
|
||||
#: ./cli/recipe/release.go:136
|
||||
msgid "unable to continue, input required for initial version"
|
||||
msgstr ""
|
||||
|
||||
@ -5152,7 +5192,7 @@ msgstr ""
|
||||
msgid "unable to create local context: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:622
|
||||
#: ./cli/recipe/release.go:600
|
||||
#, c-format
|
||||
msgid "unable to delete tag %s: %s"
|
||||
msgstr ""
|
||||
@ -5197,6 +5237,11 @@ msgstr ""
|
||||
msgid "unable to git pull in %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:583
|
||||
#, c-format
|
||||
msgid "unable to hard reset %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/app/env.go:158
|
||||
#, c-format
|
||||
msgid "unable to inspect container for %s: %s"
|
||||
@ -5226,12 +5271,12 @@ msgstr ""
|
||||
msgid "unable to open git work tree in %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:595 ./cli/recipe/release.go:617
|
||||
#: ./cli/recipe/release.go:573 ./cli/recipe/release.go:595
|
||||
#, c-format
|
||||
msgid "unable to open repo in %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:600
|
||||
#: ./cli/recipe/release.go:578
|
||||
#, c-format
|
||||
msgid "unable to open work tree in %s: %s"
|
||||
msgstr ""
|
||||
@ -5311,6 +5356,11 @@ msgstr ""
|
||||
msgid "unable to render to JSON: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:303
|
||||
#, c-format
|
||||
msgid "unable to reset commit after failed release attempt: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/recipe/git.go:166
|
||||
#, c-format
|
||||
msgid "unable to resolve '%s': %s"
|
||||
@ -5351,11 +5401,6 @@ msgstr ""
|
||||
msgid "unable to setup input stream: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:605
|
||||
#, c-format
|
||||
msgid "unable to soft reset %s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/internal/validate.go:84
|
||||
#, c-format
|
||||
msgid "unable to validate recipe: %s"
|
||||
@ -5525,7 +5570,7 @@ msgstr ""
|
||||
msgid "use local server"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:461
|
||||
#: ./cli/recipe/release.go:438
|
||||
msgid "use release note in release/next?"
|
||||
msgstr ""
|
||||
|
||||
@ -5734,7 +5779,7 @@ msgstr ""
|
||||
msgid "which service are you looking for?"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:148
|
||||
#: ./cli/recipe/release.go:158
|
||||
msgid "which version do you want to begin with?"
|
||||
msgstr ""
|
||||
|
||||
@ -5746,7 +5791,7 @@ msgstr ""
|
||||
msgid "wire up healthchecks"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:106
|
||||
#: ./cli/recipe/release.go:116
|
||||
#, c-format
|
||||
msgid "working directory not clean in %s, aborting"
|
||||
msgstr ""
|
||||
@ -5761,11 +5806,11 @@ msgstr ""
|
||||
msgid "writing recipe version failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:654 ./cli/recipe/upgrade.go:376
|
||||
#: ./cli/recipe/release.go:632 ./cli/recipe/upgrade.go:376
|
||||
msgid "x"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:662 ./cli/recipe/upgrade.go:384
|
||||
#: ./cli/recipe/release.go:640 ./cli/recipe/upgrade.go:384
|
||||
msgid "y"
|
||||
msgstr ""
|
||||
|
||||
@ -5773,11 +5818,11 @@ msgstr ""
|
||||
msgid "you can only use one of: --major, --minor, --patch."
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:243
|
||||
#: ./cli/recipe/release.go:248
|
||||
msgid "you can only use one version flag: --major, --minor or --patch"
|
||||
msgstr ""
|
||||
|
||||
#: ./cli/recipe/release.go:670 ./cli/recipe/upgrade.go:392
|
||||
#: ./cli/recipe/release.go:648 ./cli/recipe/upgrade.go:392
|
||||
msgid "z"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -5,12 +5,15 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"coopcloud.tech/abra/pkg/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsDirty(t *testing.T) {
|
||||
r := Get("abra-test-recipe")
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := Get(test.RecipeName)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -22,10 +25,9 @@ func TestIsDirty(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
defer t.Cleanup(func() {
|
||||
os.Remove(fpath)
|
||||
})
|
||||
t.Cleanup(func() { os.Remove(fpath) })
|
||||
|
||||
dirty, err := r.IsDirty()
|
||||
if err != nil {
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/test"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -101,24 +102,24 @@ func TestGet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) {
|
||||
r := Get("traefik")
|
||||
test.Setup()
|
||||
t.Cleanup(func() { test.Teardown() })
|
||||
|
||||
r := Get(test.RecipeName)
|
||||
if err := r.EnsureExists(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 1; i < 50; i++ {
|
||||
timeout := "120"
|
||||
if err := test.AddEnv("TIMEOUT", timeout); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 1; i < 3; i++ {
|
||||
label, err := r.GetVersionLabelLocal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// NOTE(d1): this is potentially quite a brittle unit test as it needs to
|
||||
// hardcode the default timeout label to ensure that the label parser never
|
||||
// returns it. hopefully this won't fail too often! if you're here because
|
||||
// of a failure, just update the `defaultTimeoutLabel` value & permalink
|
||||
// below
|
||||
// https://git.coopcloud.tech/coop-cloud/traefik/src/commit/ac3a47fe8ca3ef92db84f64cfedfbb348000faee/.env.sample#L2
|
||||
defaultTimeoutLabel := "300"
|
||||
assert.NotEqual(t, label, defaultTimeoutLabel)
|
||||
assert.NotEqual(t, label, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ package secret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
@ -39,6 +41,14 @@ type Secret struct {
|
||||
// variable. For Example:
|
||||
// SECRET_FOO=v1 # charset=default,special
|
||||
Charset string
|
||||
// Encoding comes from the encoding modifier at the secret version environment
|
||||
// variable. For Example:
|
||||
// SECRET_FOO=v1 # encoding=base64
|
||||
Encoding string
|
||||
// Prefix comes from the prefix modifier at the secret version environment
|
||||
// variable. For Example:
|
||||
// SECRET_FOO=v1 # prefix=base64:
|
||||
Prefix string
|
||||
// Whether or not to skip generation of the secret or not
|
||||
// For example: SECRET_FOO=v1 # generate=false
|
||||
SkipGenerate bool
|
||||
@ -87,6 +97,17 @@ func GeneratePassphrase() (string, error) {
|
||||
return passphrases[0], nil
|
||||
}
|
||||
|
||||
// generateRandomBytes generates random bytes as a string
|
||||
func generateRandomBytes(length int) (string, error) {
|
||||
randomBytes := make([]byte, length)
|
||||
if _, err := rand.Read(randomBytes); err != nil {
|
||||
return "", errors.New(i18n.G("failed to generate random bytes: %w", err))
|
||||
}
|
||||
|
||||
// Return as string for consistent handling with other secret types
|
||||
return string(randomBytes), nil
|
||||
}
|
||||
|
||||
// ReadSecretsConfig reads secret names/versions from the recipe config. The
|
||||
// function generalises appEnv/composeFiles because some times you have an app
|
||||
// and some times you don't (as the caller). We need to be able to handle the
|
||||
@ -177,6 +198,8 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
||||
}
|
||||
|
||||
value.Charset = resolveCharset(modifierValues["charset"])
|
||||
value.Encoding = resolveEncoding(value.Charset, modifierValues["encoding"], secretId)
|
||||
value.Prefix = modifierValues["prefix"]
|
||||
break
|
||||
}
|
||||
secretValues[secretId] = value
|
||||
@ -185,11 +208,45 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
||||
return secretValues, nil
|
||||
}
|
||||
|
||||
// encodeSecret applies encoding to the generated secret value
|
||||
func encodeSecret(value, encoding string) string {
|
||||
switch strings.ToLower(encoding) {
|
||||
case "base64":
|
||||
return base64.StdEncoding.EncodeToString([]byte(value))
|
||||
default:
|
||||
return value // No encoding applied
|
||||
}
|
||||
}
|
||||
|
||||
// applyPrefix adds a prefix to the secret value
|
||||
func applyPrefix(value, prefix string) string {
|
||||
if prefix != "" {
|
||||
return prefix + value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// resolveEncoding validates and resolves the encoding for a given charset and secretId
|
||||
func resolveEncoding(charset, encoding, secretId string) string {
|
||||
if charset == "bytes" {
|
||||
if encoding == "" {
|
||||
return "base64"
|
||||
} else if encoding != "base64" {
|
||||
log.Warnf(i18n.G("charset=bytes only supports encoding=base64, got encoding=%s for secret %s, defaulting to base64", encoding, secretId))
|
||||
return "base64"
|
||||
}
|
||||
}
|
||||
|
||||
return encoding
|
||||
}
|
||||
|
||||
// resolveCharset sets the passgen Alphabet required for a secret
|
||||
func resolveCharset(input string) string {
|
||||
switch strings.ToLower(input) {
|
||||
case "hex":
|
||||
return passgen.AlphabetNumericAmbiguous + "abcdef"
|
||||
case "bytes":
|
||||
return "bytes"
|
||||
case "special":
|
||||
return passgen.AlphabetSpecial
|
||||
case "safespecial":
|
||||
@ -224,12 +281,23 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
|
||||
log.Debug(i18n.G("attempting to generate and store %s on %s", secret.RemoteName, server))
|
||||
|
||||
if secret.Length > 0 {
|
||||
password, err := GeneratePassword(uint(secret.Length), secret.Charset)
|
||||
var password string
|
||||
var err error
|
||||
|
||||
if secret.Charset == "bytes" {
|
||||
password, err = generateRandomBytes(secret.Length)
|
||||
} else {
|
||||
password, err = GeneratePassword(uint(secret.Length), secret.Charset)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
|
||||
password = encodeSecret(password, secret.Encoding)
|
||||
password = applyPrefix(password, secret.Prefix)
|
||||
|
||||
if err := client.StoreSecret(cl, secret.RemoteName, password); err != nil {
|
||||
if strings.Contains(err.Error(), "AlreadyExists") {
|
||||
log.Warnf(i18n.G("%s already exists", secret.RemoteName))
|
||||
@ -250,6 +318,9 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
|
||||
return
|
||||
}
|
||||
|
||||
passphrase = encodeSecret(passphrase, secret.Encoding)
|
||||
passphrase = applyPrefix(passphrase, secret.Prefix)
|
||||
|
||||
if err := client.StoreSecret(cl, secret.RemoteName, passphrase); err != nil {
|
||||
if strings.Contains(err.Error(), "AlreadyExists") {
|
||||
log.Warnf(i18n.G("%s already exists", secret.RemoteName))
|
||||
|
||||
@ -18,42 +18,80 @@ func TestReadSecretsConfig(t *testing.T) {
|
||||
assert.Equal(t, "v2", secretsFromConfig["test_pass_one"].Version)
|
||||
assert.Equal(t, 0, secretsFromConfig["test_pass_one"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", secretsFromConfig["test_pass_one"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_one"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_one"].Prefix)
|
||||
|
||||
// Has a length modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_two_v1", secretsFromConfig["test_pass_two"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_two"].Version)
|
||||
assert.Equal(t, 10, secretsFromConfig["test_pass_two"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", secretsFromConfig["test_pass_two"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_two"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_two"].Prefix)
|
||||
|
||||
// Secret name does not include the secret id
|
||||
assert.Equal(t, "test_example_com_pass_three_v2", secretsFromConfig["test_pass_three"].RemoteName)
|
||||
assert.Equal(t, "v2", secretsFromConfig["test_pass_three"].Version)
|
||||
assert.Equal(t, 0, secretsFromConfig["test_pass_three"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", secretsFromConfig["test_pass_three"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_three"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_three"].Prefix)
|
||||
|
||||
// Has a length modifier and a charset=default,safespecial modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_four_v1", secretsFromConfig["test_pass_four"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_four"].Version)
|
||||
assert.Equal(t, 12, secretsFromConfig["test_pass_four"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#%^&*_-+=", secretsFromConfig["test_pass_four"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_four"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_four"].Prefix)
|
||||
|
||||
// Has a length modifier and a charset=default,special modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_five_v1", secretsFromConfig["test_pass_five"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_five"].Version)
|
||||
assert.Equal(t, 12, secretsFromConfig["test_pass_five"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*_-+=", secretsFromConfig["test_pass_five"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_five"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_five"].Prefix)
|
||||
|
||||
// Has only a charset=default,special modifier, which gets setted but ignored in the generation
|
||||
assert.Equal(t, "test_example_com_test_pass_six_v1", secretsFromConfig["test_pass_six"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_six"].Version)
|
||||
assert.Equal(t, 0, secretsFromConfig["test_pass_six"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*_-+=", secretsFromConfig["test_pass_six"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_six"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_six"].Prefix)
|
||||
|
||||
// Has a length modifier and a charset=hex modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_seven_v1", secretsFromConfig["test_pass_seven"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_seven"].Version)
|
||||
assert.Equal(t, 32, secretsFromConfig["test_pass_seven"].Length)
|
||||
assert.Equal(t, "0123456789abcdef", secretsFromConfig["test_pass_seven"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_seven"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_seven"].Prefix)
|
||||
|
||||
// Has a length modifier and an encoding=base64 modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_eight_v1", secretsFromConfig["test_pass_eight"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_eight"].Version)
|
||||
assert.Equal(t, 12, secretsFromConfig["test_pass_eight"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", secretsFromConfig["test_pass_eight"].Charset)
|
||||
assert.Equal(t, "base64", secretsFromConfig["test_pass_eight"].Encoding)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_eight"].Prefix)
|
||||
|
||||
// Has a length modifier and a prefix=base64: modifier
|
||||
assert.Equal(t, "test_example_com_test_pass_nine_v1", secretsFromConfig["test_pass_nine"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_nine"].Version)
|
||||
assert.Equal(t, 16, secretsFromConfig["test_pass_nine"].Length)
|
||||
assert.Equal(t, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", secretsFromConfig["test_pass_nine"].Charset)
|
||||
assert.Equal(t, "", secretsFromConfig["test_pass_nine"].Encoding)
|
||||
assert.Equal(t, "base64:", secretsFromConfig["test_pass_nine"].Prefix)
|
||||
|
||||
// Has all modifiers: length, charset=bytes, and prefix=base64: (Laravel-style)
|
||||
assert.Equal(t, "test_example_com_test_pass_ten_v1", secretsFromConfig["test_pass_ten"].RemoteName)
|
||||
assert.Equal(t, "v1", secretsFromConfig["test_pass_ten"].Version)
|
||||
assert.Equal(t, 32, secretsFromConfig["test_pass_ten"].Length)
|
||||
assert.Equal(t, "bytes", secretsFromConfig["test_pass_ten"].Charset)
|
||||
assert.Equal(t, "base64", secretsFromConfig["test_pass_ten"].Encoding) // Defaults to base64 for bytes
|
||||
assert.Equal(t, "base64:", secretsFromConfig["test_pass_ten"].Prefix)
|
||||
}
|
||||
|
||||
func TestReadSecretsConfigWithLongDomain(t *testing.T) {
|
||||
@ -64,3 +102,48 @@ func TestReadSecretsConfigWithLongDomain(t *testing.T) {
|
||||
}
|
||||
assert.Contains(t, err.Error(), "is > 64 chars")
|
||||
}
|
||||
|
||||
func TestEncodeSecret(t *testing.T) {
|
||||
// base64 encoding
|
||||
input := "testpassword123"
|
||||
encoded := encodeSecret(input, "base64")
|
||||
expected := "dGVzdHBhc3N3b3JkMTIz"
|
||||
assert.Equal(t, expected, encoded)
|
||||
|
||||
// no encoding (default)
|
||||
noEncoding := encodeSecret(input, "")
|
||||
assert.Equal(t, input, noEncoding)
|
||||
|
||||
// unknown encoding (should return original)
|
||||
unknownEncoding := encodeSecret(input, "unknown")
|
||||
assert.Equal(t, input, unknownEncoding)
|
||||
}
|
||||
|
||||
func TestApplyPrefix(t *testing.T) {
|
||||
input := "testvalue"
|
||||
|
||||
// with prefix
|
||||
prefixed := applyPrefix(input, "base64:")
|
||||
assert.Equal(t, "base64:testvalue", prefixed)
|
||||
|
||||
// with empty prefix
|
||||
noPrefixed := applyPrefix(input, "")
|
||||
assert.Equal(t, input, noPrefixed)
|
||||
}
|
||||
|
||||
func TestGenerateRandomBytes(t *testing.T) {
|
||||
// random bytes generation with 32 bytes
|
||||
key, err := generateRandomBytes(32)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 32, len([]byte(key))) // Check raw byte length
|
||||
|
||||
// random bytes generation with 16 bytes
|
||||
key16, err := generateRandomBytes(16)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 16, len([]byte(key16))) // Check raw byte length
|
||||
|
||||
// that keys are different (randomness)
|
||||
key2, err := generateRandomBytes(32)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEqual(t, key, key2)
|
||||
}
|
||||
|
||||
@ -5,3 +5,6 @@ SECRET_TEST_PASS_FOUR_VERSION=v1 # length=12 charset=default,safespecial
|
||||
SECRET_TEST_PASS_FIVE_VERSION=v1 # length=12 charset=default,special
|
||||
SECRET_TEST_PASS_SIX_VERSION=v1 # charset=default,special
|
||||
SECRET_TEST_PASS_SEVEN_VERSION=v1 # length=32 charset=hex
|
||||
SECRET_TEST_PASS_EIGHT_VERSION=v1 # length=12 encoding=base64
|
||||
SECRET_TEST_PASS_NINE_VERSION=v1 # length=16 prefix=base64:
|
||||
SECRET_TEST_PASS_TEN_VERSION=v1 # length=32 charset=bytes prefix=base64:
|
||||
|
||||
@ -12,6 +12,9 @@ services:
|
||||
- test_pass_five
|
||||
- test_pass_six
|
||||
- test_pass_seven
|
||||
- test_pass_eight
|
||||
- test_pass_nine
|
||||
- test_pass_ten
|
||||
|
||||
secrets:
|
||||
test_pass_one:
|
||||
@ -35,3 +38,12 @@ secrets:
|
||||
test_pass_seven:
|
||||
external: true
|
||||
name: ${STACK_NAME}_test_pass_seven_${SECRET_TEST_PASS_SEVEN_VERSION}
|
||||
test_pass_eight:
|
||||
external: true
|
||||
name: ${STACK_NAME}_test_pass_eight_${SECRET_TEST_PASS_EIGHT_VERSION}
|
||||
test_pass_nine:
|
||||
external: true
|
||||
name: ${STACK_NAME}_test_pass_nine_${SECRET_TEST_PASS_NINE_VERSION}
|
||||
test_pass_ten:
|
||||
external: true
|
||||
name: ${STACK_NAME}_test_pass_ten_${SECRET_TEST_PASS_TEN_VERSION}
|
||||
|
||||
@ -2,57 +2,50 @@ package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
appPkg "coopcloud.tech/abra/pkg/app"
|
||||
"coopcloud.tech/abra/pkg/envfile"
|
||||
"coopcloud.tech/abra/pkg/log"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
gitPkg "coopcloud.tech/abra/pkg/git"
|
||||
"git.coopcloud.tech/toolshed/godotenv"
|
||||
)
|
||||
|
||||
var (
|
||||
AppName = "test_app.example.com"
|
||||
ServerName = "test_server"
|
||||
TFiles = []string{"bar.env", "foo.env"}
|
||||
TFolders = []string{"dir1", "dir2"}
|
||||
TestServer = os.ExpandEnv("$PWD/../../tests/resources/test_server")
|
||||
TestDir = os.ExpandEnv("$PWD/../../tests/resources/test_dir")
|
||||
RecipeName = "test_recipe"
|
||||
|
||||
ExpectedAppEnv = envfile.AppEnv{
|
||||
"DOMAIN": "test_app.example.com",
|
||||
"RECIPE": "test_recipe",
|
||||
}
|
||||
TFiles = []string{"bar.env", "foo.env"}
|
||||
TFolders = []string{"dir1", "dir2"}
|
||||
|
||||
ExpectedApp = appPkg.App{
|
||||
Name: AppName,
|
||||
Recipe: recipe.Get(ExpectedAppEnv["RECIPE"]),
|
||||
Domain: ExpectedAppEnv["DOMAIN"],
|
||||
Env: ExpectedAppEnv,
|
||||
Path: ExpectedAppFile.Path,
|
||||
Server: ExpectedAppFile.Server,
|
||||
}
|
||||
ServerDir = os.ExpandEnv("$ABRA_DIR/servers/test_server")
|
||||
RecipeDir = os.ExpandEnv("$ABRA_DIR/recipes/test_recipe")
|
||||
TestDir = os.ExpandEnv("$PWD/../../tests/resources/test_dir")
|
||||
|
||||
ExpectedAppFile = appPkg.AppFile{
|
||||
Path: path.Join(TestServer, fmt.Sprintf("%s.env", AppName)),
|
||||
Server: ServerName,
|
||||
}
|
||||
AppEnvPath = path.Join(ServerDir, fmt.Sprintf("%s.env", AppName))
|
||||
|
||||
ExpectedAppFiles = map[string]appPkg.AppFile{
|
||||
AppName: ExpectedAppFile,
|
||||
}
|
||||
AbraTestRecipe = "abra-test-recipe"
|
||||
)
|
||||
|
||||
func RmServerAppRecipe() {
|
||||
testAppLink := os.ExpandEnv("$ABRA_DIR/servers/test_server")
|
||||
os.Remove(testAppLink)
|
||||
func Teardown() {
|
||||
abraDir := os.ExpandEnv("$ABRA_DIR")
|
||||
if abraDir == fmt.Sprintf("%s/.abra", os.ExpandEnv("$HOME")) {
|
||||
log.Fatal("set $ABRA_DIR before running the test suite")
|
||||
}
|
||||
|
||||
testRecipeLink := os.ExpandEnv("$ABRA_DIR/recipes/test_recipe")
|
||||
os.Remove(testRecipeLink)
|
||||
if err := os.RemoveAll(abraDir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func MkServerAppRecipe() {
|
||||
RmServerAppRecipe()
|
||||
func Setup() {
|
||||
Teardown()
|
||||
|
||||
if err := os.Mkdir(os.ExpandEnv("$ABRA_DIR"), 0764); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Mkdir(os.ExpandEnv("$ABRA_DIR/servers"), 0700); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
@ -66,15 +59,36 @@ func MkServerAppRecipe() {
|
||||
}
|
||||
}
|
||||
|
||||
testAppDir := os.ExpandEnv("$PWD/../../tests/resources/test_server")
|
||||
testAppLink := os.ExpandEnv("$ABRA_DIR/servers/test_server")
|
||||
if err := os.Symlink(testAppDir, testAppLink); err != nil {
|
||||
serverSrcDir := os.ExpandEnv("$PWD/../../tests/resources/test_server")
|
||||
serverDestDir := os.ExpandEnv("$ABRA_DIR/servers/test_server")
|
||||
if err := os.CopyFS(serverDestDir, os.DirFS(serverSrcDir)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
testRecipeDir := os.ExpandEnv("$PWD/../../tests/resources/test_recipe")
|
||||
testRecipeLink := os.ExpandEnv("$ABRA_DIR/recipes/test_recipe")
|
||||
if err := os.Symlink(testRecipeDir, testRecipeLink); err != nil {
|
||||
recipeSrcDir := os.ExpandEnv("$PWD/../../tests/resources/test_recipe")
|
||||
recipeDestDir := os.ExpandEnv("$ABRA_DIR/recipes/test_recipe")
|
||||
if err := os.CopyFS(recipeDestDir, os.DirFS(recipeSrcDir)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := gitPkg.Init(recipeDestDir, true, "tester", "helo@coopcloud.tech"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AddEnv(envKey, envValue string) error {
|
||||
filePath := os.ExpandEnv(fmt.Sprintf("$ABRA_DIR/servers/%s/%s.env", ServerName, AppName))
|
||||
|
||||
envVars, _, err := godotenv.Read(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
envVars[envKey] = envValue
|
||||
|
||||
if err := godotenv.Write(envVars, filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ func loadConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
||||
|
||||
config, err := loader.ParseYAML(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("%s: %s", filename, err)
|
||||
}
|
||||
|
||||
return &composetypes.ConfigFile{
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
"gomodTidy"
|
||||
],
|
||||
"ignoreDeps": [
|
||||
"github.com/urfave/cli",
|
||||
"goreleaser/goreleaser"
|
||||
"github.com/docker/cli",
|
||||
"github.com/spf13/cobra"
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ABRA_VERSION="0.12.0-beta"
|
||||
ABRA_VERSION="0.13.0-beta"
|
||||
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION"
|
||||
RC_VERSION="0.13.0-rc1-beta"
|
||||
RC_VERSION="0.13.0-beta"
|
||||
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION"
|
||||
|
||||
for arg in "$@"; do
|
||||
|
||||
@ -50,7 +50,7 @@ echo "========================================================================"
|
||||
echo "========================================================================"
|
||||
echo "BUILDING ABRA"
|
||||
echo "========================================================================"
|
||||
export PATH="/usr/lib/go-1.21/bin:$PATH"
|
||||
export PATH="$PATH:/usr/local/go/bin"
|
||||
make build
|
||||
echo "========================================================================"
|
||||
|
||||
|
||||
@ -87,8 +87,10 @@ teardown(){
|
||||
assert_success
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "bail if recipe lint errors and no --chaos" {
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout main
|
||||
assert_success
|
||||
|
||||
# Break the recipe
|
||||
run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
|
||||
assert_success
|
||||
@ -100,8 +102,8 @@ teardown(){
|
||||
assert_success
|
||||
|
||||
# Make a broken release
|
||||
run $ABRA recipe sync --patch "$TEST_RECIPE"
|
||||
run $ABRA recipe release --patch -n "$TEST_RECIPE"
|
||||
assert_success
|
||||
|
||||
# Make sure we deploy latest
|
||||
_wipe_env_version
|
||||
|
||||
@ -217,3 +217,53 @@ teardown() {
|
||||
assert_failure
|
||||
assert_output --partial "automagic insertion not supported yet"
|
||||
}
|
||||
|
||||
@test "push during release fails" {
|
||||
tagHash=$(_get_tag_hash "0.2.0+1.21.0")
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
|
||||
assert_success
|
||||
|
||||
run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch --commit
|
||||
assert_success
|
||||
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show
|
||||
assert_success
|
||||
assert_output --partial 'image: nginx:1.21.6'
|
||||
|
||||
wantHash="$(_get_current_hash)"
|
||||
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/does/not/exist"
|
||||
assert_success
|
||||
|
||||
run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
|
||||
assert_failure
|
||||
assert_output --partial 'failed to publish new release:'
|
||||
assert_output --partial 'any changes made have been reverted'
|
||||
|
||||
assert_equal "$wantHash" "$(_get_current_hash)"
|
||||
|
||||
assert_equal "$(_git_status)" ""
|
||||
}
|
||||
|
||||
@test "release, fail, release: works" {
|
||||
tagHash=$(_get_tag_hash "0.2.0+1.21.0")
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
|
||||
assert_success
|
||||
|
||||
run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch --commit
|
||||
assert_success
|
||||
|
||||
# NOTE(d1): fake broken remote so the release fails
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/does/not/exist"
|
||||
assert_success
|
||||
|
||||
run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
|
||||
assert_failure
|
||||
|
||||
# NOTE(d1): correct remote so release can proceed
|
||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" remote set-url origin-ssh "$ABRA_DIR/origin-recipes/$TEST_RECIPE.git"
|
||||
assert_success
|
||||
|
||||
run $ABRA recipe release "$TEST_RECIPE" --no-input --patch
|
||||
assert_success
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
RECIPE=test_recipe
|
||||
DOMAIN=test_app.example.com
|
||||
|
||||
# NOTE(d1): ensure commented out TIMEOUT doesn't get included
|
||||
# see TestReadEnv in ./pkg/envfile
|
||||
# TIMEOUT=120
|
||||
#
|
||||
# NOTE(d1): for new changes, you *MUST* also update ../test_server/test_app.example.com.env
|
||||
#
|
||||
|
||||
# NOTE(d1): TestReadEnv
|
||||
# FOO=BAR
|
||||
|
||||
@ -8,6 +8,7 @@ services:
|
||||
- proxy
|
||||
deploy:
|
||||
labels:
|
||||
- "coop-cloud.${STACK_NAME}.version=0.1.0+0.1.0"
|
||||
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT}"
|
||||
|
||||
networks:
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
RECIPE=test_recipe
|
||||
DOMAIN=test_app.example.com
|
||||
|
||||
# NOTE(d1): ensure commented out TIMEOUT doesn't get included
|
||||
# see TestReadEnv in ./pkg/envfile
|
||||
# TIMEOUT=120
|
||||
#
|
||||
# NOTE(d1): for new changes, you *MUST* also update ../test_recipe/.env.sample
|
||||
#
|
||||
|
||||
# NOTE(d1): TestReadEnv
|
||||
# FOO=BAR
|
||||
|
||||
2
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
2
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
@ -1,7 +1,7 @@
|
||||
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
|
||||
reflection interface similar to Go's standard library `json` and `xml` packages.
|
||||
|
||||
Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
|
||||
Compatible with TOML version [v1.1.0](https://toml.io/en/v1.1.0).
|
||||
|
||||
Documentation: https://pkg.go.dev/github.com/BurntSushi/toml
|
||||
|
||||
|
||||
9
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
9
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
@ -206,6 +206,13 @@ func markDecodedRecursive(md *MetaData, tmap map[string]any) {
|
||||
markDecodedRecursive(md, tmap)
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
}
|
||||
if tarr, ok := tmap[key].([]map[string]any); ok {
|
||||
for _, elm := range tarr {
|
||||
md.context = append(md.context, key)
|
||||
markDecodedRecursive(md, elm)
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +430,7 @@ func (md *MetaData) unifyString(data any, rv reflect.Value) error {
|
||||
if i, ok := data.(int64); ok {
|
||||
rv.SetString(strconv.FormatInt(i, 10))
|
||||
} else if f, ok := data.(float64); ok {
|
||||
rv.SetString(strconv.FormatFloat(f, 'f', -1, 64))
|
||||
rv.SetString(strconv.FormatFloat(f, 'g', -1, 64))
|
||||
} else {
|
||||
return md.badtype("string", data)
|
||||
}
|
||||
|
||||
79
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
79
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
@ -228,9 +228,9 @@ func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
}
|
||||
switch v.Location() {
|
||||
default:
|
||||
enc.wf(v.Format(format))
|
||||
enc.write(v.Format(format))
|
||||
case internal.LocalDatetime, internal.LocalDate, internal.LocalTime:
|
||||
enc.wf(v.In(time.UTC).Format(format))
|
||||
enc.write(v.In(time.UTC).Format(format))
|
||||
}
|
||||
return
|
||||
case Marshaler:
|
||||
@ -279,40 +279,40 @@ func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
case reflect.String:
|
||||
enc.writeQuoted(rv.String())
|
||||
case reflect.Bool:
|
||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
||||
enc.write(strconv.FormatBool(rv.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
||||
enc.write(strconv.FormatInt(rv.Int(), 10))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
||||
enc.write(strconv.FormatUint(rv.Uint(), 10))
|
||||
case reflect.Float32:
|
||||
f := rv.Float()
|
||||
if math.IsNaN(f) {
|
||||
if math.Signbit(f) {
|
||||
enc.wf("-")
|
||||
enc.write("-")
|
||||
}
|
||||
enc.wf("nan")
|
||||
enc.write("nan")
|
||||
} else if math.IsInf(f, 0) {
|
||||
if math.Signbit(f) {
|
||||
enc.wf("-")
|
||||
enc.write("-")
|
||||
}
|
||||
enc.wf("inf")
|
||||
enc.write("inf")
|
||||
} else {
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32)))
|
||||
enc.write(floatAddDecimal(strconv.FormatFloat(f, 'g', -1, 32)))
|
||||
}
|
||||
case reflect.Float64:
|
||||
f := rv.Float()
|
||||
if math.IsNaN(f) {
|
||||
if math.Signbit(f) {
|
||||
enc.wf("-")
|
||||
enc.write("-")
|
||||
}
|
||||
enc.wf("nan")
|
||||
enc.write("nan")
|
||||
} else if math.IsInf(f, 0) {
|
||||
if math.Signbit(f) {
|
||||
enc.wf("-")
|
||||
enc.write("-")
|
||||
}
|
||||
enc.wf("inf")
|
||||
enc.write("inf")
|
||||
} else {
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64)))
|
||||
enc.write(floatAddDecimal(strconv.FormatFloat(f, 'g', -1, 64)))
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
enc.eArrayOrSliceElement(rv)
|
||||
@ -330,27 +330,32 @@ func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
// By the TOML spec, all floats must have a decimal with at least one number on
|
||||
// either side.
|
||||
func floatAddDecimal(fstr string) string {
|
||||
if !strings.Contains(fstr, ".") {
|
||||
return fstr + ".0"
|
||||
for _, c := range fstr {
|
||||
if c == 'e' { // Exponent syntax
|
||||
return fstr
|
||||
}
|
||||
if c == '.' {
|
||||
return fstr
|
||||
}
|
||||
}
|
||||
return fstr
|
||||
return fstr + ".0"
|
||||
}
|
||||
|
||||
func (enc *Encoder) writeQuoted(s string) {
|
||||
enc.wf("\"%s\"", dblQuotedReplacer.Replace(s))
|
||||
enc.write(`"` + dblQuotedReplacer.Replace(s) + `"`)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
|
||||
length := rv.Len()
|
||||
enc.wf("[")
|
||||
enc.write("[")
|
||||
for i := 0; i < length; i++ {
|
||||
elem := eindirect(rv.Index(i))
|
||||
enc.eElement(elem)
|
||||
if i != length-1 {
|
||||
enc.wf(", ")
|
||||
enc.write(", ")
|
||||
}
|
||||
}
|
||||
enc.wf("]")
|
||||
enc.write("]")
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
||||
@ -363,7 +368,7 @@ func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
||||
continue
|
||||
}
|
||||
enc.newline()
|
||||
enc.wf("%s[[%s]]", enc.indentStr(key), key)
|
||||
enc.writef("%s[[%s]]", enc.indentStr(key), key)
|
||||
enc.newline()
|
||||
enc.eMapOrStruct(key, trv, false)
|
||||
}
|
||||
@ -376,7 +381,7 @@ func (enc *Encoder) eTable(key Key, rv reflect.Value) {
|
||||
enc.newline()
|
||||
}
|
||||
if len(key) > 0 {
|
||||
enc.wf("%s[%s]", enc.indentStr(key), key)
|
||||
enc.writef("%s[%s]", enc.indentStr(key), key)
|
||||
enc.newline()
|
||||
}
|
||||
enc.eMapOrStruct(key, rv, false)
|
||||
@ -422,7 +427,7 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
|
||||
if inline {
|
||||
enc.writeKeyValue(Key{mapKey.String()}, val, true)
|
||||
if trailC || i != len(mapKeys)-1 {
|
||||
enc.wf(", ")
|
||||
enc.write(", ")
|
||||
}
|
||||
} else {
|
||||
enc.encode(key.add(mapKey.String()), val)
|
||||
@ -431,12 +436,12 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
|
||||
}
|
||||
|
||||
if inline {
|
||||
enc.wf("{")
|
||||
enc.write("{")
|
||||
}
|
||||
writeMapKeys(mapKeysDirect, len(mapKeysSub) > 0)
|
||||
writeMapKeys(mapKeysSub, false)
|
||||
if inline {
|
||||
enc.wf("}")
|
||||
enc.write("}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,7 +539,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
if inline {
|
||||
enc.writeKeyValue(Key{keyName}, fieldVal, true)
|
||||
if fieldIndex[0] != totalFields-1 {
|
||||
enc.wf(", ")
|
||||
enc.write(", ")
|
||||
}
|
||||
} else {
|
||||
enc.encode(key.add(keyName), fieldVal)
|
||||
@ -543,14 +548,14 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
}
|
||||
|
||||
if inline {
|
||||
enc.wf("{")
|
||||
enc.write("{")
|
||||
}
|
||||
|
||||
l := len(fieldsDirect) + len(fieldsSub)
|
||||
writeFields(fieldsDirect, l)
|
||||
writeFields(fieldsSub, l)
|
||||
if inline {
|
||||
enc.wf("}")
|
||||
enc.write("}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,7 +705,7 @@ func isEmpty(rv reflect.Value) bool {
|
||||
|
||||
func (enc *Encoder) newline() {
|
||||
if enc.hasWritten {
|
||||
enc.wf("\n")
|
||||
enc.write("\n")
|
||||
}
|
||||
}
|
||||
|
||||
@ -722,14 +727,22 @@ func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) {
|
||||
enc.eElement(val)
|
||||
return
|
||||
}
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.writef("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
if !inline {
|
||||
enc.newline()
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) wf(format string, v ...any) {
|
||||
func (enc *Encoder) write(s string) {
|
||||
_, err := enc.w.WriteString(s)
|
||||
if err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
enc.hasWritten = true
|
||||
}
|
||||
|
||||
func (enc *Encoder) writef(format string, v ...any) {
|
||||
_, err := fmt.Fprintf(enc.w, format, v...)
|
||||
if err != nil {
|
||||
encPanic(err)
|
||||
|
||||
130
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
130
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
@ -13,7 +13,6 @@ type itemType int
|
||||
|
||||
const (
|
||||
itemError itemType = iota
|
||||
itemNIL // used in the parser to indicate no type
|
||||
itemEOF
|
||||
itemText
|
||||
itemString
|
||||
@ -47,14 +46,13 @@ func (p Position) String() string {
|
||||
}
|
||||
|
||||
type lexer struct {
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
tomlNext bool
|
||||
esc bool
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
esc bool
|
||||
|
||||
// Allow for backing up up to 4 runes. This is necessary because TOML
|
||||
// contains 3-rune tokens (""" and ''').
|
||||
@ -90,14 +88,13 @@ func (lx *lexer) nextItem() item {
|
||||
}
|
||||
}
|
||||
|
||||
func lex(input string, tomlNext bool) *lexer {
|
||||
func lex(input string) *lexer {
|
||||
lx := &lexer{
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
tomlNext: tomlNext,
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
}
|
||||
return lx
|
||||
}
|
||||
@ -108,7 +105,7 @@ func (lx *lexer) push(state stateFn) {
|
||||
|
||||
func (lx *lexer) pop() stateFn {
|
||||
if len(lx.stack) == 0 {
|
||||
return lx.errorf("BUG in lexer: no states to pop")
|
||||
panic("BUG in lexer: no states to pop")
|
||||
}
|
||||
last := lx.stack[len(lx.stack)-1]
|
||||
lx.stack = lx.stack[0 : len(lx.stack)-1]
|
||||
@ -305,6 +302,8 @@ func lexTop(lx *lexer) stateFn {
|
||||
return lexTableStart
|
||||
case eof:
|
||||
if lx.pos > lx.start {
|
||||
// TODO: never reached? I think this can only occur on a bug in the
|
||||
// lexer(?)
|
||||
return lx.errorf("unexpected EOF")
|
||||
}
|
||||
lx.emit(itemEOF)
|
||||
@ -392,8 +391,6 @@ func lexTableNameStart(lx *lexer) stateFn {
|
||||
func lexTableNameEnd(lx *lexer) stateFn {
|
||||
lx.skip(isWhitespace)
|
||||
switch r := lx.next(); {
|
||||
case isWhitespace(r):
|
||||
return lexTableNameEnd
|
||||
case r == '.':
|
||||
lx.ignore()
|
||||
return lexTableNameStart
|
||||
@ -412,7 +409,7 @@ func lexTableNameEnd(lx *lexer) stateFn {
|
||||
// Lexes only one part, e.g. only 'a' inside 'a.b'.
|
||||
func lexBareName(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isBareKeyChar(r, lx.tomlNext) {
|
||||
if isBareKeyChar(r) {
|
||||
return lexBareName
|
||||
}
|
||||
lx.backup()
|
||||
@ -420,23 +417,23 @@ func lexBareName(lx *lexer) stateFn {
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexBareName lexes one part of a key or table.
|
||||
//
|
||||
// It assumes that at least one valid character for the table has already been
|
||||
// read.
|
||||
// lexQuotedName lexes one part of a quoted key or table name. It assumes that
|
||||
// it starts lexing at the quote itself (" or ').
|
||||
//
|
||||
// Lexes only one part, e.g. only '"a"' inside '"a".b'.
|
||||
func lexQuotedName(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexValue)
|
||||
case r == '"':
|
||||
lx.ignore() // ignore the '"'
|
||||
return lexString
|
||||
case r == '\'':
|
||||
lx.ignore() // ignore the "'"
|
||||
return lexRawString
|
||||
|
||||
// TODO: I don't think any of the below conditions can ever be reached?
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexValue)
|
||||
case r == eof:
|
||||
return lx.errorf("unexpected EOF; expected value")
|
||||
default:
|
||||
@ -464,17 +461,19 @@ func lexKeyStart(lx *lexer) stateFn {
|
||||
func lexKeyNameStart(lx *lexer) stateFn {
|
||||
lx.skip(isWhitespace)
|
||||
switch r := lx.peek(); {
|
||||
case r == '=' || r == eof:
|
||||
return lx.errorf("unexpected '='")
|
||||
case r == '.':
|
||||
return lx.errorf("unexpected '.'")
|
||||
default:
|
||||
lx.push(lexKeyEnd)
|
||||
return lexBareName
|
||||
case r == '"' || r == '\'':
|
||||
lx.ignore()
|
||||
lx.push(lexKeyEnd)
|
||||
return lexQuotedName
|
||||
default:
|
||||
lx.push(lexKeyEnd)
|
||||
return lexBareName
|
||||
|
||||
// TODO: I think these can never be reached?
|
||||
case r == '=' || r == eof:
|
||||
return lx.errorf("unexpected '='")
|
||||
case r == '.':
|
||||
return lx.errorf("unexpected '.'")
|
||||
}
|
||||
}
|
||||
|
||||
@ -485,7 +484,7 @@ func lexKeyEnd(lx *lexer) stateFn {
|
||||
switch r := lx.next(); {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexKeyEnd)
|
||||
case r == eof:
|
||||
case r == eof: // TODO: never reached
|
||||
return lx.errorf("unexpected EOF; expected key separator '='")
|
||||
case r == '.':
|
||||
lx.ignore()
|
||||
@ -628,10 +627,7 @@ func lexInlineTableValue(lx *lexer) stateFn {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValue)
|
||||
return lexCommentStart
|
||||
@ -653,10 +649,7 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValueEnd)
|
||||
return lexCommentStart
|
||||
@ -664,10 +657,7 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
||||
lx.ignore()
|
||||
lx.skip(isWhitespace)
|
||||
if lx.peek() == '}' {
|
||||
if lx.tomlNext {
|
||||
return lexInlineTableValueEnd
|
||||
}
|
||||
return lx.errorf("trailing comma not allowed in inline tables")
|
||||
return lexInlineTableValueEnd
|
||||
}
|
||||
return lexInlineTableValue
|
||||
case r == '}':
|
||||
@ -855,9 +845,6 @@ func lexStringEscape(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch r {
|
||||
case 'e':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
fallthrough
|
||||
case 'b':
|
||||
fallthrough
|
||||
@ -878,9 +865,6 @@ func lexStringEscape(lx *lexer) stateFn {
|
||||
case '\\':
|
||||
return lx.pop()
|
||||
case 'x':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
return lexHexEscape
|
||||
case 'u':
|
||||
return lexShortUnicodeEscape
|
||||
@ -928,19 +912,9 @@ func lexLongUnicodeEscape(lx *lexer) stateFn {
|
||||
// lexBaseNumberOrDate can differentiate base prefixed integers from other
|
||||
// types.
|
||||
func lexNumberOrDateStart(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch r {
|
||||
case '0':
|
||||
if lx.next() == '0' {
|
||||
return lexBaseNumberOrDate
|
||||
}
|
||||
|
||||
if !isDigit(r) {
|
||||
// The only way to reach this state is if the value starts
|
||||
// with a digit, so specifically treat anything else as an
|
||||
// error.
|
||||
return lx.errorf("expected a digit but got %q", r)
|
||||
}
|
||||
|
||||
return lexNumberOrDate
|
||||
}
|
||||
|
||||
@ -1196,13 +1170,13 @@ func lexSkip(lx *lexer, nextState stateFn) stateFn {
|
||||
}
|
||||
|
||||
func (s stateFn) String() string {
|
||||
if s == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
name := runtime.FuncForPC(reflect.ValueOf(s).Pointer()).Name()
|
||||
if i := strings.LastIndexByte(name, '.'); i > -1 {
|
||||
name = name[i+1:]
|
||||
}
|
||||
if s == nil {
|
||||
name = "<nil>"
|
||||
}
|
||||
return name + "()"
|
||||
}
|
||||
|
||||
@ -1210,8 +1184,6 @@ func (itype itemType) String() string {
|
||||
switch itype {
|
||||
case itemError:
|
||||
return "Error"
|
||||
case itemNIL:
|
||||
return "NIL"
|
||||
case itemEOF:
|
||||
return "EOF"
|
||||
case itemText:
|
||||
@ -1226,18 +1198,22 @@ func (itype itemType) String() string {
|
||||
return "Float"
|
||||
case itemDatetime:
|
||||
return "DateTime"
|
||||
case itemTableStart:
|
||||
return "TableStart"
|
||||
case itemTableEnd:
|
||||
return "TableEnd"
|
||||
case itemKeyStart:
|
||||
return "KeyStart"
|
||||
case itemKeyEnd:
|
||||
return "KeyEnd"
|
||||
case itemArray:
|
||||
return "Array"
|
||||
case itemArrayEnd:
|
||||
return "ArrayEnd"
|
||||
case itemTableStart:
|
||||
return "TableStart"
|
||||
case itemTableEnd:
|
||||
return "TableEnd"
|
||||
case itemArrayTableStart:
|
||||
return "ArrayTableStart"
|
||||
case itemArrayTableEnd:
|
||||
return "ArrayTableEnd"
|
||||
case itemKeyStart:
|
||||
return "KeyStart"
|
||||
case itemKeyEnd:
|
||||
return "KeyEnd"
|
||||
case itemCommentStart:
|
||||
return "CommentStart"
|
||||
case itemInlineTableStart:
|
||||
@ -1266,7 +1242,7 @@ func isDigit(r rune) bool { return r >= '0' && r <= '9' }
|
||||
func isBinary(r rune) bool { return r == '0' || r == '1' }
|
||||
func isOctal(r rune) bool { return r >= '0' && r <= '7' }
|
||||
func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') }
|
||||
func isBareKeyChar(r rune, tomlNext bool) bool {
|
||||
func isBareKeyChar(r rune) bool {
|
||||
return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') || r == '_' || r == '-'
|
||||
}
|
||||
|
||||
46
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
46
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
@ -3,7 +3,6 @@ package toml
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -17,7 +16,6 @@ type parser struct {
|
||||
context Key // Full key for the current hash in scope.
|
||||
currentKey string // Base key name for everything except hashes.
|
||||
pos Position // Current position in the TOML file.
|
||||
tomlNext bool
|
||||
|
||||
ordered []Key // List of keys in the order that they appear in the TOML data.
|
||||
|
||||
@ -32,8 +30,6 @@ type keyInfo struct {
|
||||
}
|
||||
|
||||
func parse(data string) (p *parser, err error) {
|
||||
_, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if pErr, ok := r.(ParseError); ok {
|
||||
@ -73,10 +69,9 @@ func parse(data string) (p *parser, err error) {
|
||||
p = &parser{
|
||||
keyInfo: make(map[string]keyInfo),
|
||||
mapping: make(map[string]any),
|
||||
lx: lex(data, tomlNext),
|
||||
lx: lex(data),
|
||||
ordered: make([]Key, 0),
|
||||
implicits: make(map[string]struct{}),
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
for {
|
||||
item := p.next()
|
||||
@ -350,17 +345,14 @@ func (p *parser) valueFloat(it item) (any, tomlType) {
|
||||
var dtTypes = []struct {
|
||||
fmt string
|
||||
zone *time.Location
|
||||
next bool
|
||||
}{
|
||||
{time.RFC3339Nano, time.Local, false},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false},
|
||||
{"2006-01-02", internal.LocalDate, false},
|
||||
{"15:04:05.999999999", internal.LocalTime, false},
|
||||
|
||||
// tomlNext
|
||||
{"2006-01-02T15:04Z07:00", time.Local, true},
|
||||
{"2006-01-02T15:04", internal.LocalDatetime, true},
|
||||
{"15:04", internal.LocalTime, true},
|
||||
{time.RFC3339Nano, time.Local},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime},
|
||||
{"2006-01-02", internal.LocalDate},
|
||||
{"15:04:05.999999999", internal.LocalTime},
|
||||
{"2006-01-02T15:04Z07:00", time.Local},
|
||||
{"2006-01-02T15:04", internal.LocalDatetime},
|
||||
{"15:04", internal.LocalTime},
|
||||
}
|
||||
|
||||
func (p *parser) valueDatetime(it item) (any, tomlType) {
|
||||
@ -371,9 +363,6 @@ func (p *parser) valueDatetime(it item) (any, tomlType) {
|
||||
err error
|
||||
)
|
||||
for _, dt := range dtTypes {
|
||||
if dt.next && !p.tomlNext {
|
||||
continue
|
||||
}
|
||||
t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
|
||||
if err == nil {
|
||||
if missingLeadingZero(it.val, dt.fmt) {
|
||||
@ -644,6 +633,11 @@ func (p *parser) setValue(key string, value any) {
|
||||
// Note that since it has already been defined (as a hash), we don't
|
||||
// want to overwrite it. So our business is done.
|
||||
if p.isArray(keyContext) {
|
||||
if !p.isImplicit(keyContext) {
|
||||
if _, ok := hash[key]; ok {
|
||||
p.panicf("Key '%s' has already been defined.", keyContext)
|
||||
}
|
||||
}
|
||||
p.removeImplicit(keyContext)
|
||||
hash[key] = value
|
||||
return
|
||||
@ -802,10 +796,8 @@ func (p *parser) replaceEscapes(it item, str string) string {
|
||||
b.WriteByte(0x0d)
|
||||
skip = 1
|
||||
case 'e':
|
||||
if p.tomlNext {
|
||||
b.WriteByte(0x1b)
|
||||
skip = 1
|
||||
}
|
||||
b.WriteByte(0x1b)
|
||||
skip = 1
|
||||
case '"':
|
||||
b.WriteByte(0x22)
|
||||
skip = 1
|
||||
@ -815,11 +807,9 @@ func (p *parser) replaceEscapes(it item, str string) string {
|
||||
// The lexer guarantees the correct number of characters are present;
|
||||
// don't need to check here.
|
||||
case 'x':
|
||||
if p.tomlNext {
|
||||
escaped := p.asciiEscapeToUnicode(it, str[i+2:i+4])
|
||||
b.WriteRune(escaped)
|
||||
skip = 3
|
||||
}
|
||||
escaped := p.asciiEscapeToUnicode(it, str[i+2:i+4])
|
||||
b.WriteRune(escaped)
|
||||
skip = 3
|
||||
case 'u':
|
||||
escaped := p.asciiEscapeToUnicode(it, str[i+2:i+6])
|
||||
b.WriteRune(escaped)
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
@ -69,6 +69,8 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
|
||||
if isPrefix {
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
// Trim the line to remove any whitespace
|
||||
line = bytes.TrimSpace(line)
|
||||
|
||||
if bytes.HasPrefix(line, armorEnd) {
|
||||
l.eof = true
|
||||
|
||||
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go
generated
vendored
@ -125,7 +125,10 @@ func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecr
|
||||
// "VB = convert point V to the octet string"
|
||||
// sharedPoint corresponds to `VB`.
|
||||
var sharedPoint x25519lib.Key
|
||||
x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
|
||||
ok := x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
|
||||
if !ok {
|
||||
return nil, nil, errors.KeyInvalidError("ecc: the public key is a low order point")
|
||||
}
|
||||
|
||||
return ephemeralPublic[:], sharedPoint[:], nil
|
||||
}
|
||||
@ -146,7 +149,10 @@ func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error)
|
||||
// RFC6637 §8: "Note that the recipient obtains the shared secret by calculating
|
||||
// S = rV = rvG, where (r,R) is the recipient's key pair."
|
||||
// sharedPoint corresponds to `S`.
|
||||
x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
|
||||
ok := x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
|
||||
if !ok {
|
||||
return nil, errors.KeyInvalidError("ecc: the public key is a low order point")
|
||||
}
|
||||
|
||||
return sharedPoint[:], nil
|
||||
}
|
||||
|
||||
5
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go
generated
vendored
5
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go
generated
vendored
@ -78,7 +78,7 @@ func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err
|
||||
func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
|
||||
xP, yP := elliptic.Unmarshal(c.Curve, point)
|
||||
if xP == nil {
|
||||
panic("invalid point")
|
||||
return nil, nil, errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
|
||||
}
|
||||
|
||||
d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
|
||||
@ -99,6 +99,9 @@ func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSe
|
||||
|
||||
func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
|
||||
x, y := elliptic.Unmarshal(c.Curve, ephemeral)
|
||||
if x == nil {
|
||||
return nil, errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
|
||||
}
|
||||
zbBig, _ := c.Curve.ScalarMult(x, y, secret)
|
||||
byteLen := (c.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
|
||||
26
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
26
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
@ -178,6 +178,18 @@ type Config struct {
|
||||
// When set to true, a key without flags is treated as if all flags are enabled.
|
||||
// This behavior is consistent with GPG.
|
||||
InsecureAllowAllKeyFlagsWhenMissing bool
|
||||
// InsecureGenerateNonCriticalKeyFlags causes the "Key Flags" signature subpacket
|
||||
// to be non-critical in newly generated signatures.
|
||||
// This may be needed for keys to be accepted by older clients who do not recognize
|
||||
// the subpacket.
|
||||
// For example, rpm 4.14.3-150400.59.3.1 in OpenSUSE Leap 15.4 does not recognize it.
|
||||
InsecureGenerateNonCriticalKeyFlags bool
|
||||
// InsecureGenerateNonCriticalSignatureCreationTime causes the "Signature Creation Time" signature subpacket
|
||||
// to be non-critical in newly generated signatures.
|
||||
// This may be needed for keys to be accepted by older clients who do not recognize
|
||||
// the subpacket.
|
||||
// For example, yum 3.4.3-168 in CentOS 7 and yum 3.4.3-158 in Amazon Linux 2 do not recognize it.
|
||||
InsecureGenerateNonCriticalSignatureCreationTime bool
|
||||
|
||||
// MaxDecompressedMessageSize specifies the maximum number of bytes that can be
|
||||
// read from a compressed packet. This serves as an upper limit to prevent
|
||||
@ -420,6 +432,20 @@ func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
|
||||
return c.InsecureAllowAllKeyFlagsWhenMissing
|
||||
}
|
||||
|
||||
func (c *Config) GenerateNonCriticalKeyFlags() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
return c.InsecureGenerateNonCriticalKeyFlags
|
||||
}
|
||||
|
||||
func (c *Config) GenerateNonCriticalSignatureCreationTime() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
return c.InsecureGenerateNonCriticalSignatureCreationTime
|
||||
}
|
||||
|
||||
func (c *Config) DecompressedMessageSizeLimit() *int64 {
|
||||
if c == nil {
|
||||
return nil
|
||||
|
||||
8
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
8
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
@ -933,7 +933,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
||||
}
|
||||
sig.Notations = append(sig.Notations, ¬ation)
|
||||
}
|
||||
sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey)
|
||||
sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1254,11 +1254,11 @@ type outputSubpacket struct {
|
||||
contents []byte
|
||||
}
|
||||
|
||||
func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) {
|
||||
func (sig *Signature) buildSubpackets(issuer PublicKey, config *Config) (subpackets []outputSubpacket, err error) {
|
||||
creationTime := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
|
||||
// Signature Creation Time
|
||||
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, true, creationTime})
|
||||
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, !config.GenerateNonCriticalSignatureCreationTime(), creationTime})
|
||||
// Signature Expiration Time
|
||||
if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
|
||||
sigLifetime := make([]byte, 4)
|
||||
@ -1357,7 +1357,7 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
|
||||
if sig.FlagGroupKey {
|
||||
flags |= KeyFlagGroupKey
|
||||
}
|
||||
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, true, []byte{flags}})
|
||||
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, !config.GenerateNonCriticalKeyFlags(), []byte{flags}})
|
||||
}
|
||||
// Signer's User ID
|
||||
if sig.SignerUserId != nil {
|
||||
|
||||
3
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
3
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
@ -33,6 +33,9 @@ linters:
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
settings:
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
47
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
47
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
@ -2,6 +2,7 @@ package colorprofile
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
@ -83,8 +84,8 @@ func colorProfile(isatty bool, env environ) (p Profile) {
|
||||
}
|
||||
|
||||
if envNoColor(env) && isatty {
|
||||
if p > Ascii {
|
||||
p = Ascii
|
||||
if p > ASCII {
|
||||
p = ASCII
|
||||
}
|
||||
return //nolint:nakedret
|
||||
}
|
||||
@ -153,29 +154,29 @@ func envColorProfile(env environ) (p Profile) {
|
||||
p = ANSI
|
||||
}
|
||||
|
||||
parts := strings.Split(term, "-")
|
||||
switch parts[0] {
|
||||
case "alacritty",
|
||||
"contour",
|
||||
"foot",
|
||||
"ghostty",
|
||||
"kitty",
|
||||
"rio",
|
||||
"st",
|
||||
"wezterm":
|
||||
switch {
|
||||
case strings.Contains(term, "alacritty"),
|
||||
strings.Contains(term, "contour"),
|
||||
strings.Contains(term, "foot"),
|
||||
strings.Contains(term, "ghostty"),
|
||||
strings.Contains(term, "kitty"),
|
||||
strings.Contains(term, "rio"),
|
||||
strings.Contains(term, "st"),
|
||||
strings.Contains(term, "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":
|
||||
case strings.HasPrefix(term, "tmux"), strings.HasPrefix(term, "screen"):
|
||||
if p < ANSI256 {
|
||||
p = ANSI256
|
||||
}
|
||||
case strings.HasPrefix(term, "xterm"):
|
||||
if p < ANSI {
|
||||
p = ANSI
|
||||
}
|
||||
}
|
||||
|
||||
if len(env["WT_SESSION"]) > 0 {
|
||||
// Windows Terminal supports TrueColor
|
||||
return TrueColor
|
||||
}
|
||||
|
||||
if isCloudShell, _ := strconv.ParseBool(env.get("GOOGLE_CLOUD_SHELL")); isCloudShell {
|
||||
@ -244,13 +245,13 @@ func tmux(env environ) (p Profile) {
|
||||
// Check if tmux has either Tc or RGB capabilities. Otherwise, return
|
||||
// ANSI256.
|
||||
p = ANSI256
|
||||
cmd := exec.Command("tmux", "info")
|
||||
cmd := exec.CommandContext(context.Background(), "tmux", "info")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, line := range bytes.Split(out, []byte("\n")) {
|
||||
for line := range bytes.SplitSeq(out, []byte("\n")) {
|
||||
if (bytes.Contains(line, []byte("Tc")) || bytes.Contains(line, []byte("RGB"))) &&
|
||||
bytes.Contains(line, []byte("true")) {
|
||||
return TrueColor
|
||||
|
||||
5
vendor/github.com/charmbracelet/colorprofile/env_windows.go
generated
vendored
5
vendor/github.com/charmbracelet/colorprofile/env_windows.go
generated
vendored
@ -14,11 +14,6 @@ func windowsColorProfile(env map[string]string) (Profile, bool) {
|
||||
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
|
||||
|
||||
26
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
26
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
@ -11,10 +11,12 @@ import (
|
||||
type Profile byte
|
||||
|
||||
const (
|
||||
// Unknown is a profile that represents the absence of a profile.
|
||||
Unknown Profile = iota
|
||||
// NoTTY is a profile with no terminal support.
|
||||
NoTTY Profile = iota
|
||||
// Ascii is a profile with no color support.
|
||||
Ascii //nolint:revive
|
||||
NoTTY
|
||||
// ASCII is a profile with no color support.
|
||||
ASCII
|
||||
// ANSI is a profile with 16 colors (4-bit).
|
||||
ANSI
|
||||
// ANSI256 is a profile with 256 colors (8-bit).
|
||||
@ -23,6 +25,9 @@ const (
|
||||
TrueColor
|
||||
)
|
||||
|
||||
// Ascii is an alias for the [ASCII] profile for backwards compatibility.
|
||||
const Ascii = ASCII //nolint:revive
|
||||
|
||||
// String returns the string representation of a Profile.
|
||||
func (p Profile) String() string {
|
||||
switch p {
|
||||
@ -32,12 +37,13 @@ func (p Profile) String() string {
|
||||
return "ANSI256"
|
||||
case ANSI:
|
||||
return "ANSI"
|
||||
case Ascii:
|
||||
case ASCII:
|
||||
return "Ascii"
|
||||
case NoTTY:
|
||||
return "NoTTY"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
var (
|
||||
@ -50,7 +56,7 @@ var (
|
||||
|
||||
// Convert transforms a given Color to a Color supported within the Profile.
|
||||
func (p Profile) Convert(c color.Color) (cc color.Color) {
|
||||
if p <= Ascii {
|
||||
if p <= ASCII {
|
||||
return nil
|
||||
}
|
||||
if p == TrueColor {
|
||||
@ -90,11 +96,13 @@ func (p Profile) Convert(c color.Color) (cc color.Color) {
|
||||
return c
|
||||
|
||||
default:
|
||||
if p == ANSI256 {
|
||||
switch p {
|
||||
case ANSI256:
|
||||
return ansi.Convert256(c)
|
||||
} else if p == ANSI {
|
||||
case ANSI:
|
||||
return ansi.Convert16(c)
|
||||
default:
|
||||
return c
|
||||
}
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
20
vendor/github.com/charmbracelet/colorprofile/writer.go
generated
vendored
20
vendor/github.com/charmbracelet/colorprofile/writer.go
generated
vendored
@ -36,13 +36,15 @@ type Writer struct {
|
||||
|
||||
// Write writes the given text to the underlying writer.
|
||||
func (w *Writer) Write(p []byte) (int, error) {
|
||||
switch w.Profile {
|
||||
case TrueColor:
|
||||
switch {
|
||||
case w.Profile == 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)
|
||||
case w.Profile <= NoTTY:
|
||||
_, err := io.WriteString(w.Forward, ansi.Strip(string(p)))
|
||||
return len(p), err
|
||||
case w.Profile == ASCII, w.Profile == ANSI, w.Profile == ANSI256:
|
||||
_, err := w.downsample(p)
|
||||
return len(p), err
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid profile: %v", w.Profile)
|
||||
}
|
||||
@ -112,7 +114,7 @@ func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) {
|
||||
if w.Profile < ANSI {
|
||||
continue
|
||||
}
|
||||
style = style.DefaultForegroundColor()
|
||||
style = style.ForegroundColor(nil)
|
||||
case 40, 41, 42, 43, 44, 45, 46, 47: // 8-bit background color
|
||||
if w.Profile < ANSI {
|
||||
continue
|
||||
@ -132,7 +134,7 @@ func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) {
|
||||
if w.Profile < ANSI {
|
||||
continue
|
||||
}
|
||||
style = style.DefaultBackgroundColor()
|
||||
style = style.BackgroundColor(nil)
|
||||
case 58: // 16 or 24-bit underline color
|
||||
var c color.Color
|
||||
if n := ansi.ReadStyleColor(params[i:], &c); n > 0 {
|
||||
@ -146,7 +148,7 @@ func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) {
|
||||
if w.Profile < ANSI {
|
||||
continue
|
||||
}
|
||||
style = style.DefaultUnderlineColor()
|
||||
style = style.UnderlineColor(nil)
|
||||
case 90, 91, 92, 93, 94, 95, 96, 97: // 8-bit bright foreground color
|
||||
if w.Profile < ANSI {
|
||||
continue
|
||||
|
||||
8
vendor/github.com/charmbracelet/log/.golangci.yml
generated
vendored
8
vendor/github.com/charmbracelet/log/.golangci.yml
generated
vendored
@ -7,7 +7,6 @@ linters:
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
@ -27,9 +26,16 @@ linters:
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
exclusions:
|
||||
rules:
|
||||
- text: '(slog|log)\.\w+'
|
||||
linters:
|
||||
- noctx
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
settings:
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
2
vendor/github.com/charmbracelet/log/json.go
generated
vendored
2
vendor/github.com/charmbracelet/log/json.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func (l *Logger) jsonFormatter(keyvals ...interface{}) {
|
||||
func (l *Logger) jsonFormatter(keyvals ...any) {
|
||||
jw := &jsonWriter{w: &l.b}
|
||||
jw.start()
|
||||
|
||||
|
||||
2
vendor/github.com/charmbracelet/log/logfmt.go
generated
vendored
2
vendor/github.com/charmbracelet/log/logfmt.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
"github.com/go-logfmt/logfmt"
|
||||
)
|
||||
|
||||
func (l *Logger) logfmtFormatter(keyvals ...interface{}) {
|
||||
func (l *Logger) logfmtFormatter(keyvals ...any) {
|
||||
e := logfmt.NewEncoder(&l.b)
|
||||
|
||||
for i := 0; i < len(keyvals); i += 2 {
|
||||
|
||||
38
vendor/github.com/charmbracelet/log/logger.go
generated
vendored
38
vendor/github.com/charmbracelet/log/logger.go
generated
vendored
@ -41,19 +41,19 @@ type Logger struct {
|
||||
reportCaller bool
|
||||
reportTimestamp bool
|
||||
|
||||
fields []interface{}
|
||||
fields []any
|
||||
|
||||
helpers *sync.Map
|
||||
styles *Styles
|
||||
}
|
||||
|
||||
// Logf logs a message with formatting.
|
||||
func (l *Logger) Logf(level Level, format string, args ...interface{}) {
|
||||
func (l *Logger) Logf(level Level, format string, args ...any) {
|
||||
l.Log(level, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Log logs the given message with the given keyvals for the given level.
|
||||
func (l *Logger) Log(level Level, msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Log(level Level, msg any, keyvals ...any) {
|
||||
if atomic.LoadUint32(&l.isDiscard) != 0 {
|
||||
return
|
||||
}
|
||||
@ -81,8 +81,8 @@ func (l *Logger) Log(level Level, msg interface{}, keyvals ...interface{}) {
|
||||
l.handle(level, l.timeFunc(time.Now()), []runtime.Frame{frame}, msg, keyvals...)
|
||||
}
|
||||
|
||||
func (l *Logger) handle(level Level, ts time.Time, frames []runtime.Frame, msg interface{}, keyvals ...interface{}) {
|
||||
var kvs []interface{}
|
||||
func (l *Logger) handle(level Level, ts time.Time, frames []runtime.Frame, msg any, keyvals ...any) {
|
||||
var kvs []any
|
||||
if l.reportTimestamp && !ts.IsZero() {
|
||||
kvs = append(kvs, TimestampKey, ts)
|
||||
}
|
||||
@ -327,7 +327,7 @@ func (l *Logger) SetStyles(s *Styles) {
|
||||
}
|
||||
|
||||
// With returns a new logger with the given keyvals added.
|
||||
func (l *Logger) With(keyvals ...interface{}) *Logger {
|
||||
func (l *Logger) With(keyvals ...any) *Logger {
|
||||
var st Styles
|
||||
l.mu.Lock()
|
||||
sl := *l
|
||||
@ -336,7 +336,7 @@ func (l *Logger) With(keyvals ...interface{}) *Logger {
|
||||
sl.b = bytes.Buffer{}
|
||||
sl.mu = &sync.RWMutex{}
|
||||
sl.helpers = &sync.Map{}
|
||||
sl.fields = append(make([]interface{}, 0, len(l.fields)+len(keyvals)), l.fields...)
|
||||
sl.fields = append(make([]any, 0, len(l.fields)+len(keyvals)), l.fields...)
|
||||
sl.fields = append(sl.fields, keyvals...)
|
||||
sl.styles = &st
|
||||
return &sl
|
||||
@ -350,63 +350,63 @@ func (l *Logger) WithPrefix(prefix string) *Logger {
|
||||
}
|
||||
|
||||
// Debug prints a debug message.
|
||||
func (l *Logger) Debug(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Debug(msg any, keyvals ...any) {
|
||||
l.Log(DebugLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Info prints an info message.
|
||||
func (l *Logger) Info(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Info(msg any, keyvals ...any) {
|
||||
l.Log(InfoLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Warn prints a warning message.
|
||||
func (l *Logger) Warn(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Warn(msg any, keyvals ...any) {
|
||||
l.Log(WarnLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Error prints an error message.
|
||||
func (l *Logger) Error(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Error(msg any, keyvals ...any) {
|
||||
l.Log(ErrorLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Fatal prints a fatal message and exits.
|
||||
func (l *Logger) Fatal(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Fatal(msg any, keyvals ...any) {
|
||||
l.Log(FatalLevel, msg, keyvals...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print prints a message with no level.
|
||||
func (l *Logger) Print(msg interface{}, keyvals ...interface{}) {
|
||||
func (l *Logger) Print(msg any, keyvals ...any) {
|
||||
l.Log(noLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Debugf prints a debug message with formatting.
|
||||
func (l *Logger) Debugf(format string, args ...interface{}) {
|
||||
func (l *Logger) Debugf(format string, args ...any) {
|
||||
l.Log(DebugLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Infof prints an info message with formatting.
|
||||
func (l *Logger) Infof(format string, args ...interface{}) {
|
||||
func (l *Logger) Infof(format string, args ...any) {
|
||||
l.Log(InfoLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Warnf prints a warning message with formatting.
|
||||
func (l *Logger) Warnf(format string, args ...interface{}) {
|
||||
func (l *Logger) Warnf(format string, args ...any) {
|
||||
l.Log(WarnLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Errorf prints an error message with formatting.
|
||||
func (l *Logger) Errorf(format string, args ...interface{}) {
|
||||
func (l *Logger) Errorf(format string, args ...any) {
|
||||
l.Log(ErrorLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Fatalf prints a fatal message with formatting and exits.
|
||||
func (l *Logger) Fatalf(format string, args ...interface{}) {
|
||||
func (l *Logger) Fatalf(format string, args ...any) {
|
||||
l.Log(FatalLevel, fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Printf prints a message with no level and formatting.
|
||||
func (l *Logger) Printf(format string, args ...interface{}) {
|
||||
func (l *Logger) Printf(format string, args ...any) {
|
||||
l.Log(noLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
4
vendor/github.com/charmbracelet/log/logger_121.go
generated
vendored
4
vendor/github.com/charmbracelet/log/logger_121.go
generated
vendored
@ -36,7 +36,7 @@ func (l *Logger) Handle(ctx context.Context, record slog.Record) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
fields := make([]interface{}, 0, record.NumAttrs()*2)
|
||||
fields := make([]any, 0, record.NumAttrs()*2)
|
||||
record.Attrs(func(a slog.Attr) bool {
|
||||
fields = append(fields, a.Key, a.Value)
|
||||
return true
|
||||
@ -52,7 +52,7 @@ func (l *Logger) Handle(ctx context.Context, record slog.Record) error {
|
||||
//
|
||||
// Implements slog.Handler.
|
||||
func (l *Logger) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
fields := make([]interface{}, 0, len(attrs)*2)
|
||||
fields := make([]any, 0, len(attrs)*2)
|
||||
for _, attr := range attrs {
|
||||
fields = append(fields, attr.Key, attr.Value)
|
||||
}
|
||||
|
||||
4
vendor/github.com/charmbracelet/log/logger_no121.go
generated
vendored
4
vendor/github.com/charmbracelet/log/logger_no121.go
generated
vendored
@ -33,7 +33,7 @@ func (l *Logger) Enabled(_ context.Context, level slog.Level) bool {
|
||||
//
|
||||
// Implements slog.Handler.
|
||||
func (l *Logger) Handle(_ context.Context, record slog.Record) error {
|
||||
fields := make([]interface{}, 0, record.NumAttrs()*2)
|
||||
fields := make([]any, 0, record.NumAttrs()*2)
|
||||
record.Attrs(func(a slog.Attr) bool {
|
||||
fields = append(fields, a.Key, a.Value)
|
||||
return true
|
||||
@ -49,7 +49,7 @@ func (l *Logger) Handle(_ context.Context, record slog.Record) error {
|
||||
//
|
||||
// Implements slog.Handler.
|
||||
func (l *Logger) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
fields := make([]interface{}, 0, len(attrs)*2)
|
||||
fields := make([]any, 0, len(attrs)*2)
|
||||
for _, attr := range attrs {
|
||||
fields = append(fields, attr.Key, attr.Value)
|
||||
}
|
||||
|
||||
2
vendor/github.com/charmbracelet/log/options.go
generated
vendored
2
vendor/github.com/charmbracelet/log/options.go
generated
vendored
@ -55,7 +55,7 @@ type Options struct {
|
||||
// CallerOffset is the caller format for the logger. The default is 0.
|
||||
CallerOffset int
|
||||
// Fields is the fields for the logger. The default is no fields.
|
||||
Fields []interface{}
|
||||
Fields []any
|
||||
// Formatter is the formatter for the logger. The default is TextFormatter.
|
||||
Formatter Formatter
|
||||
}
|
||||
|
||||
30
vendor/github.com/charmbracelet/log/pkg.go
generated
vendored
30
vendor/github.com/charmbracelet/log/pkg.go
generated
vendored
@ -155,7 +155,7 @@ func GetPrefix() string {
|
||||
}
|
||||
|
||||
// With returns a new logger with the given keyvals.
|
||||
func With(keyvals ...interface{}) *Logger {
|
||||
func With(keyvals ...any) *Logger {
|
||||
return Default().With(keyvals...)
|
||||
}
|
||||
|
||||
@ -172,74 +172,74 @@ func Helper() {
|
||||
}
|
||||
|
||||
// Log logs a message with the given level.
|
||||
func Log(level Level, msg interface{}, keyvals ...interface{}) {
|
||||
func Log(level Level, msg any, keyvals ...any) {
|
||||
Default().Log(level, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Debug logs a debug message.
|
||||
func Debug(msg interface{}, keyvals ...interface{}) {
|
||||
func Debug(msg any, keyvals ...any) {
|
||||
Default().Log(DebugLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Info logs an info message.
|
||||
func Info(msg interface{}, keyvals ...interface{}) {
|
||||
func Info(msg any, keyvals ...any) {
|
||||
Default().Log(InfoLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Warn logs a warning message.
|
||||
func Warn(msg interface{}, keyvals ...interface{}) {
|
||||
func Warn(msg any, keyvals ...any) {
|
||||
Default().Log(WarnLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Error logs an error message.
|
||||
func Error(msg interface{}, keyvals ...interface{}) {
|
||||
func Error(msg any, keyvals ...any) {
|
||||
Default().Log(ErrorLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Fatal logs a fatal message and exit.
|
||||
func Fatal(msg interface{}, keyvals ...interface{}) {
|
||||
func Fatal(msg any, keyvals ...any) {
|
||||
Default().Log(FatalLevel, msg, keyvals...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print logs a message with no level.
|
||||
func Print(msg interface{}, keyvals ...interface{}) {
|
||||
func Print(msg any, keyvals ...any) {
|
||||
Default().Log(noLevel, msg, keyvals...)
|
||||
}
|
||||
|
||||
// Logf logs a message with formatting and level.
|
||||
func Logf(level Level, format string, args ...interface{}) {
|
||||
func Logf(level Level, format string, args ...any) {
|
||||
Default().Logf(level, format, args...)
|
||||
}
|
||||
|
||||
// Debugf logs a debug message with formatting.
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
func Debugf(format string, args ...any) {
|
||||
Default().Log(DebugLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Infof logs an info message with formatting.
|
||||
func Infof(format string, args ...interface{}) {
|
||||
func Infof(format string, args ...any) {
|
||||
Default().Log(InfoLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Warnf logs a warning message with formatting.
|
||||
func Warnf(format string, args ...interface{}) {
|
||||
func Warnf(format string, args ...any) {
|
||||
Default().Log(WarnLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Errorf logs an error message with formatting.
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
func Errorf(format string, args ...any) {
|
||||
Default().Log(ErrorLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Fatalf logs a fatal message with formatting and exit.
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
func Fatalf(format string, args ...any) {
|
||||
Default().Log(FatalLevel, fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Printf logs a message with formatting and no level.
|
||||
func Printf(format string, args ...interface{}) {
|
||||
func Printf(format string, args ...any) {
|
||||
Default().Log(noLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
|
||||
4
vendor/github.com/charmbracelet/log/text.go
generated
vendored
4
vendor/github.com/charmbracelet/log/text.go
generated
vendored
@ -62,7 +62,7 @@ const (
|
||||
)
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return new(strings.Builder)
|
||||
},
|
||||
}
|
||||
@ -164,7 +164,7 @@ func writeSpace(w io.Writer, first bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) textFormatter(keyvals ...interface{}) {
|
||||
func (l *Logger) textFormatter(keyvals ...any) {
|
||||
st := l.styles
|
||||
lenKeyvals := len(keyvals)
|
||||
|
||||
|
||||
6
vendor/github.com/charmbracelet/x/ansi/cursor.go
generated
vendored
6
vendor/github.com/charmbracelet/x/ansi/cursor.go
generated
vendored
@ -261,7 +261,7 @@ func CHA(col int) string {
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/CUP.html
|
||||
func CursorPosition(col, row int) string {
|
||||
if row <= 0 && col <= 0 {
|
||||
if row <= 1 && col <= 1 {
|
||||
return CursorHomePosition
|
||||
}
|
||||
|
||||
@ -281,7 +281,9 @@ func CUP(col, row int) string {
|
||||
}
|
||||
|
||||
// CursorHomePosition is a sequence for moving the cursor to the upper left
|
||||
// corner of the scrolling region. This is equivalent to `CursorPosition(1, 1)`.
|
||||
// corner of the scrolling region.
|
||||
//
|
||||
// This is equivalent to [CursorPosition](1, 1).
|
||||
const CursorHomePosition = "\x1b[H"
|
||||
|
||||
// SetCursorPosition (CUP) returns a sequence for setting the cursor to the
|
||||
|
||||
24
vendor/github.com/charmbracelet/x/ansi/method.go
generated
vendored
24
vendor/github.com/charmbracelet/x/ansi/method.go
generated
vendored
@ -1,5 +1,29 @@
|
||||
package ansi
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/clipperhouse/displaywidth"
|
||||
"github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
var wcOptions = &runewidth.Condition{
|
||||
EastAsianWidth: false,
|
||||
StrictEmojiNeutral: true,
|
||||
}
|
||||
|
||||
var dwOptions = &displaywidth.Options{
|
||||
EastAsianWidth: false,
|
||||
}
|
||||
|
||||
func init() {
|
||||
if ea, err := strconv.ParseBool(os.Getenv("RUNEWIDTH_EASTASIAN")); err == nil && ea {
|
||||
wcOptions.EastAsianWidth = true
|
||||
dwOptions.EastAsianWidth = true
|
||||
}
|
||||
}
|
||||
|
||||
// Method is a type that represents the how the renderer should calculate the
|
||||
// display width of cells.
|
||||
type Method uint8
|
||||
|
||||
465
vendor/github.com/charmbracelet/x/ansi/mode.go
generated
vendored
465
vendor/github.com/charmbracelet/x/ansi/mode.go
generated
vendored
@ -108,7 +108,7 @@ func DECRST(modes ...Mode) string {
|
||||
|
||||
func setMode(reset bool, modes ...Mode) (s string) {
|
||||
if len(modes) == 0 {
|
||||
return //nolint:nakedret
|
||||
return s
|
||||
}
|
||||
|
||||
cmd := "h"
|
||||
@ -142,7 +142,7 @@ func setMode(reset bool, modes ...Mode) (s string) {
|
||||
if len(dec) > 0 {
|
||||
s += seq + "?" + strings.Join(dec, ";") + cmd
|
||||
}
|
||||
return //nolint:nakedret
|
||||
return s
|
||||
}
|
||||
|
||||
// RequestMode (DECRQM) returns a sequence to request a mode from the terminal.
|
||||
@ -228,12 +228,12 @@ func (m DECMode) Mode() int {
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/KAM.html
|
||||
const (
|
||||
KeyboardActionMode = ANSIMode(2)
|
||||
KAM = KeyboardActionMode
|
||||
ModeKeyboardAction = ANSIMode(2)
|
||||
KAM = ModeKeyboardAction
|
||||
|
||||
SetKeyboardActionMode = "\x1b[2h"
|
||||
ResetKeyboardActionMode = "\x1b[2l"
|
||||
RequestKeyboardActionMode = "\x1b[2$p"
|
||||
SetModeKeyboardAction = "\x1b[2h"
|
||||
ResetModeKeyboardAction = "\x1b[2l"
|
||||
RequestModeKeyboardAction = "\x1b[2$p"
|
||||
)
|
||||
|
||||
// Insert/Replace Mode (IRM) is a mode that determines whether characters are
|
||||
@ -245,12 +245,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/IRM.html
|
||||
const (
|
||||
InsertReplaceMode = ANSIMode(4)
|
||||
IRM = InsertReplaceMode
|
||||
ModeInsertReplace = ANSIMode(4)
|
||||
IRM = ModeInsertReplace
|
||||
|
||||
SetInsertReplaceMode = "\x1b[4h"
|
||||
ResetInsertReplaceMode = "\x1b[4l"
|
||||
RequestInsertReplaceMode = "\x1b[4$p"
|
||||
SetModeInsertReplace = "\x1b[4h"
|
||||
ResetModeInsertReplace = "\x1b[4l"
|
||||
RequestModeInsertReplace = "\x1b[4$p"
|
||||
)
|
||||
|
||||
// BiDirectional Support Mode (BDSM) is a mode that determines whether the
|
||||
@ -260,12 +260,12 @@ const (
|
||||
//
|
||||
// See ECMA-48 7.2.1.
|
||||
const (
|
||||
BiDirectionalSupportMode = ANSIMode(8)
|
||||
BDSM = BiDirectionalSupportMode
|
||||
ModeBiDirectionalSupport = ANSIMode(8)
|
||||
BDSM = ModeBiDirectionalSupport
|
||||
|
||||
SetBiDirectionalSupportMode = "\x1b[8h"
|
||||
ResetBiDirectionalSupportMode = "\x1b[8l"
|
||||
RequestBiDirectionalSupportMode = "\x1b[8$p"
|
||||
SetModeBiDirectionalSupport = "\x1b[8h"
|
||||
ResetModeBiDirectionalSupport = "\x1b[8l"
|
||||
RequestModeBiDirectionalSupport = "\x1b[8$p"
|
||||
)
|
||||
|
||||
// Send Receive Mode (SRM) or Local Echo Mode is a mode that determines whether
|
||||
@ -274,17 +274,17 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/SRM.html
|
||||
const (
|
||||
SendReceiveMode = ANSIMode(12)
|
||||
LocalEchoMode = SendReceiveMode
|
||||
SRM = SendReceiveMode
|
||||
ModeSendReceive = ANSIMode(12)
|
||||
ModeLocalEcho = ModeSendReceive
|
||||
SRM = ModeSendReceive
|
||||
|
||||
SetSendReceiveMode = "\x1b[12h"
|
||||
ResetSendReceiveMode = "\x1b[12l"
|
||||
RequestSendReceiveMode = "\x1b[12$p"
|
||||
SetModeSendReceive = "\x1b[12h"
|
||||
ResetModeSendReceive = "\x1b[12l"
|
||||
RequestModeSendReceive = "\x1b[12$p"
|
||||
|
||||
SetLocalEchoMode = "\x1b[12h"
|
||||
ResetLocalEchoMode = "\x1b[12l"
|
||||
RequestLocalEchoMode = "\x1b[12$p"
|
||||
SetModeLocalEcho = "\x1b[12h"
|
||||
ResetModeLocalEcho = "\x1b[12l"
|
||||
RequestModeLocalEcho = "\x1b[12$p"
|
||||
)
|
||||
|
||||
// Line Feed/New Line Mode (LNM) is a mode that determines whether the terminal
|
||||
@ -299,12 +299,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/LNM.html
|
||||
const (
|
||||
LineFeedNewLineMode = ANSIMode(20)
|
||||
LNM = LineFeedNewLineMode
|
||||
ModeLineFeedNewLine = ANSIMode(20)
|
||||
LNM = ModeLineFeedNewLine
|
||||
|
||||
SetLineFeedNewLineMode = "\x1b[20h"
|
||||
ResetLineFeedNewLineMode = "\x1b[20l"
|
||||
RequestLineFeedNewLineMode = "\x1b[20$p"
|
||||
SetModeLineFeedNewLine = "\x1b[20h"
|
||||
ResetModeLineFeedNewLine = "\x1b[20l"
|
||||
RequestModeLineFeedNewLine = "\x1b[20$p"
|
||||
)
|
||||
|
||||
// Cursor Keys Mode (DECCKM) is a mode that determines whether the cursor keys
|
||||
@ -312,18 +312,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECCKM.html
|
||||
const (
|
||||
CursorKeysMode = DECMode(1)
|
||||
DECCKM = CursorKeysMode
|
||||
ModeCursorKeys = DECMode(1)
|
||||
DECCKM = ModeCursorKeys
|
||||
|
||||
SetCursorKeysMode = "\x1b[?1h"
|
||||
ResetCursorKeysMode = "\x1b[?1l"
|
||||
RequestCursorKeysMode = "\x1b[?1$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetCursorKeysMode] and [ResetCursorKeysMode] instead.
|
||||
const (
|
||||
EnableCursorKeys = "\x1b[?1h" //nolint:revive // grouped constants
|
||||
DisableCursorKeys = "\x1b[?1l"
|
||||
SetModeCursorKeys = "\x1b[?1h"
|
||||
ResetModeCursorKeys = "\x1b[?1l"
|
||||
RequestModeCursorKeys = "\x1b[?1$p"
|
||||
)
|
||||
|
||||
// Origin Mode (DECOM) is a mode that determines whether the cursor moves to the
|
||||
@ -331,12 +325,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECOM.html
|
||||
const (
|
||||
OriginMode = DECMode(6)
|
||||
DECOM = OriginMode
|
||||
ModeOrigin = DECMode(6)
|
||||
DECOM = ModeOrigin
|
||||
|
||||
SetOriginMode = "\x1b[?6h"
|
||||
ResetOriginMode = "\x1b[?6l"
|
||||
RequestOriginMode = "\x1b[?6$p"
|
||||
SetModeOrigin = "\x1b[?6h"
|
||||
ResetModeOrigin = "\x1b[?6l"
|
||||
RequestModeOrigin = "\x1b[?6$p"
|
||||
)
|
||||
|
||||
// Auto Wrap Mode (DECAWM) is a mode that determines whether the cursor wraps
|
||||
@ -344,12 +338,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECAWM.html
|
||||
const (
|
||||
AutoWrapMode = DECMode(7)
|
||||
DECAWM = AutoWrapMode
|
||||
ModeAutoWrap = DECMode(7)
|
||||
DECAWM = ModeAutoWrap
|
||||
|
||||
SetAutoWrapMode = "\x1b[?7h"
|
||||
ResetAutoWrapMode = "\x1b[?7l"
|
||||
RequestAutoWrapMode = "\x1b[?7$p"
|
||||
SetModeAutoWrap = "\x1b[?7h"
|
||||
ResetModeAutoWrap = "\x1b[?7l"
|
||||
RequestModeAutoWrap = "\x1b[?7$p"
|
||||
)
|
||||
|
||||
// X10 Mouse Mode is a mode that determines whether the mouse reports on button
|
||||
@ -364,39 +358,29 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
X10MouseMode = DECMode(9)
|
||||
ModeMouseX10 = DECMode(9)
|
||||
|
||||
SetX10MouseMode = "\x1b[?9h"
|
||||
ResetX10MouseMode = "\x1b[?9l"
|
||||
RequestX10MouseMode = "\x1b[?9$p"
|
||||
SetModeMouseX10 = "\x1b[?9h"
|
||||
ResetModeMouseX10 = "\x1b[?9l"
|
||||
RequestModeMouseX10 = "\x1b[?9$p"
|
||||
)
|
||||
|
||||
// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor.
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECTCEM.html
|
||||
const (
|
||||
TextCursorEnableMode = DECMode(25)
|
||||
DECTCEM = TextCursorEnableMode
|
||||
ModeTextCursorEnable = DECMode(25)
|
||||
DECTCEM = ModeTextCursorEnable
|
||||
|
||||
SetTextCursorEnableMode = "\x1b[?25h"
|
||||
ResetTextCursorEnableMode = "\x1b[?25l"
|
||||
RequestTextCursorEnableMode = "\x1b[?25$p"
|
||||
SetModeTextCursorEnable = "\x1b[?25h"
|
||||
ResetModeTextCursorEnable = "\x1b[?25l"
|
||||
RequestModeTextCursorEnable = "\x1b[?25$p"
|
||||
)
|
||||
|
||||
// These are aliases for [SetTextCursorEnableMode] and [ResetTextCursorEnableMode].
|
||||
// These are aliases for [SetModeTextCursorEnable] and [ResetModeTextCursorEnable].
|
||||
const (
|
||||
ShowCursor = SetTextCursorEnableMode
|
||||
HideCursor = ResetTextCursorEnableMode
|
||||
)
|
||||
|
||||
// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor.
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECTCEM.html
|
||||
//
|
||||
// Deprecated: use [SetTextCursorEnableMode] and [ResetTextCursorEnableMode] instead.
|
||||
const (
|
||||
CursorEnableMode = DECMode(25)
|
||||
RequestCursorVisibility = "\x1b[?25$p"
|
||||
ShowCursor = SetModeTextCursorEnable
|
||||
HideCursor = ResetModeTextCursorEnable
|
||||
)
|
||||
|
||||
// Numeric Keypad Mode (DECNKM) is a mode that determines whether the keypad
|
||||
@ -406,12 +390,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECNKM.html
|
||||
const (
|
||||
NumericKeypadMode = DECMode(66)
|
||||
DECNKM = NumericKeypadMode
|
||||
ModeNumericKeypad = DECMode(66)
|
||||
DECNKM = ModeNumericKeypad
|
||||
|
||||
SetNumericKeypadMode = "\x1b[?66h"
|
||||
ResetNumericKeypadMode = "\x1b[?66l"
|
||||
RequestNumericKeypadMode = "\x1b[?66$p"
|
||||
SetModeNumericKeypad = "\x1b[?66h"
|
||||
ResetModeNumericKeypad = "\x1b[?66l"
|
||||
RequestModeNumericKeypad = "\x1b[?66$p"
|
||||
)
|
||||
|
||||
// Backarrow Key Mode (DECBKM) is a mode that determines whether the backspace
|
||||
@ -419,12 +403,12 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECBKM.html
|
||||
const (
|
||||
BackarrowKeyMode = DECMode(67)
|
||||
DECBKM = BackarrowKeyMode
|
||||
ModeBackarrowKey = DECMode(67)
|
||||
DECBKM = ModeBackarrowKey
|
||||
|
||||
SetBackarrowKeyMode = "\x1b[?67h"
|
||||
ResetBackarrowKeyMode = "\x1b[?67l"
|
||||
RequestBackarrowKeyMode = "\x1b[?67$p"
|
||||
SetModeBackarrowKey = "\x1b[?67h"
|
||||
ResetModeBackarrowKey = "\x1b[?67l"
|
||||
RequestModeBackarrowKey = "\x1b[?67$p"
|
||||
)
|
||||
|
||||
// Left Right Margin Mode (DECLRMM) is a mode that determines whether the left
|
||||
@ -432,47 +416,33 @@ const (
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECLRMM.html
|
||||
const (
|
||||
LeftRightMarginMode = DECMode(69)
|
||||
DECLRMM = LeftRightMarginMode
|
||||
ModeLeftRightMargin = DECMode(69)
|
||||
DECLRMM = ModeLeftRightMargin
|
||||
|
||||
SetLeftRightMarginMode = "\x1b[?69h"
|
||||
ResetLeftRightMarginMode = "\x1b[?69l"
|
||||
RequestLeftRightMarginMode = "\x1b[?69$p"
|
||||
SetModeLeftRightMargin = "\x1b[?69h"
|
||||
ResetModeLeftRightMargin = "\x1b[?69l"
|
||||
RequestModeLeftRightMargin = "\x1b[?69$p"
|
||||
)
|
||||
|
||||
// Normal Mouse Mode is a mode that determines whether the mouse reports on
|
||||
// button presses and releases. It will also report modifier keys, wheel
|
||||
// events, and extra buttons.
|
||||
//
|
||||
// It uses the same encoding as [X10MouseMode] with a few differences:
|
||||
// It uses the same encoding as [ModeMouseX10] with a few differences:
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
NormalMouseMode = DECMode(1000)
|
||||
ModeMouseNormal = DECMode(1000)
|
||||
|
||||
SetNormalMouseMode = "\x1b[?1000h"
|
||||
ResetNormalMouseMode = "\x1b[?1000l"
|
||||
RequestNormalMouseMode = "\x1b[?1000$p"
|
||||
)
|
||||
|
||||
// VT Mouse Tracking is a mode that determines whether the mouse reports on
|
||||
// button press and release.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
//
|
||||
// Deprecated: use [NormalMouseMode] instead.
|
||||
const (
|
||||
MouseMode = DECMode(1000)
|
||||
|
||||
EnableMouse = "\x1b[?1000h"
|
||||
DisableMouse = "\x1b[?1000l"
|
||||
RequestMouse = "\x1b[?1000$p"
|
||||
SetModeMouseNormal = "\x1b[?1000h"
|
||||
ResetModeMouseNormal = "\x1b[?1000l"
|
||||
RequestModeMouseNormal = "\x1b[?1000$p"
|
||||
)
|
||||
|
||||
// Highlight Mouse Tracking is a mode that determines whether the mouse reports
|
||||
// on button presses, releases, and highlighted cells.
|
||||
//
|
||||
// It uses the same encoding as [NormalMouseMode] with a few differences:
|
||||
// It uses the same encoding as [ModeMouseNormal] with a few differences:
|
||||
//
|
||||
// On highlight events, the terminal responds with the following encoding:
|
||||
//
|
||||
@ -481,11 +451,11 @@ const (
|
||||
//
|
||||
// Where the parameters are startx, starty, endx, endy, mousex, and mousey.
|
||||
const (
|
||||
HighlightMouseMode = DECMode(1001)
|
||||
ModeMouseHighlight = DECMode(1001)
|
||||
|
||||
SetHighlightMouseMode = "\x1b[?1001h"
|
||||
ResetHighlightMouseMode = "\x1b[?1001l"
|
||||
RequestHighlightMouseMode = "\x1b[?1001$p"
|
||||
SetModeMouseHighlight = "\x1b[?1001h"
|
||||
ResetModeMouseHighlight = "\x1b[?1001l"
|
||||
RequestModeMouseHighlight = "\x1b[?1001$p"
|
||||
)
|
||||
|
||||
// VT Hilite Mouse Tracking is a mode that determines whether the mouse reports on
|
||||
@ -493,65 +463,29 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
//
|
||||
// Deprecated: use [HighlightMouseMode] instead.
|
||||
const (
|
||||
MouseHiliteMode = DECMode(1001)
|
||||
|
||||
EnableMouseHilite = "\x1b[?1001h"
|
||||
DisableMouseHilite = "\x1b[?1001l"
|
||||
RequestMouseHilite = "\x1b[?1001$p"
|
||||
)
|
||||
|
||||
// Button Event Mouse Tracking is essentially the same as [NormalMouseMode],
|
||||
// Button Event Mouse Tracking is essentially the same as [ModeMouseNormal],
|
||||
// but it also reports button-motion events when a button is pressed.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
ButtonEventMouseMode = DECMode(1002)
|
||||
ModeMouseButtonEvent = DECMode(1002)
|
||||
|
||||
SetButtonEventMouseMode = "\x1b[?1002h"
|
||||
ResetButtonEventMouseMode = "\x1b[?1002l"
|
||||
RequestButtonEventMouseMode = "\x1b[?1002$p"
|
||||
SetModeMouseButtonEvent = "\x1b[?1002h"
|
||||
ResetModeMouseButtonEvent = "\x1b[?1002l"
|
||||
RequestModeMouseButtonEvent = "\x1b[?1002$p"
|
||||
)
|
||||
|
||||
// Cell Motion Mouse Tracking is a mode that determines whether the mouse
|
||||
// reports on button press, release, and motion events.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
//
|
||||
// Deprecated: use [ButtonEventMouseMode] instead.
|
||||
const (
|
||||
MouseCellMotionMode = DECMode(1002)
|
||||
|
||||
EnableMouseCellMotion = "\x1b[?1002h"
|
||||
DisableMouseCellMotion = "\x1b[?1002l"
|
||||
RequestMouseCellMotion = "\x1b[?1002$p"
|
||||
)
|
||||
|
||||
// Any Event Mouse Tracking is the same as [ButtonEventMouseMode], except that
|
||||
// Any Event Mouse Tracking is the same as [ModeMouseButtonEvent], except that
|
||||
// all motion events are reported even if no mouse buttons are pressed.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
AnyEventMouseMode = DECMode(1003)
|
||||
ModeMouseAnyEvent = DECMode(1003)
|
||||
|
||||
SetAnyEventMouseMode = "\x1b[?1003h"
|
||||
ResetAnyEventMouseMode = "\x1b[?1003l"
|
||||
RequestAnyEventMouseMode = "\x1b[?1003$p"
|
||||
)
|
||||
|
||||
// All Mouse Tracking is a mode that determines whether the mouse reports on
|
||||
// button press, release, motion, and highlight events.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
//
|
||||
// Deprecated: use [AnyEventMouseMode] instead.
|
||||
const (
|
||||
MouseAllMotionMode = DECMode(1003)
|
||||
|
||||
EnableMouseAllMotion = "\x1b[?1003h"
|
||||
DisableMouseAllMotion = "\x1b[?1003l"
|
||||
RequestMouseAllMotion = "\x1b[?1003$p"
|
||||
SetModeMouseAnyEvent = "\x1b[?1003h"
|
||||
ResetModeMouseAnyEvent = "\x1b[?1003l"
|
||||
RequestModeMouseAnyEvent = "\x1b[?1003$p"
|
||||
)
|
||||
|
||||
// Focus Event Mode is a mode that determines whether the terminal reports focus
|
||||
@ -564,22 +498,11 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Focus-Tracking
|
||||
const (
|
||||
FocusEventMode = DECMode(1004)
|
||||
ModeFocusEvent = DECMode(1004)
|
||||
|
||||
SetFocusEventMode = "\x1b[?1004h"
|
||||
ResetFocusEventMode = "\x1b[?1004l"
|
||||
RequestFocusEventMode = "\x1b[?1004$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetFocusEventMode], [ResetFocusEventMode], and
|
||||
// [RequestFocusEventMode] instead.
|
||||
// Focus reporting mode constants.
|
||||
const (
|
||||
ReportFocusMode = DECMode(1004) //nolint:revive // grouped constants
|
||||
|
||||
EnableReportFocus = "\x1b[?1004h"
|
||||
DisableReportFocus = "\x1b[?1004l"
|
||||
RequestReportFocus = "\x1b[?1004$p"
|
||||
SetModeFocusEvent = "\x1b[?1004h"
|
||||
ResetModeFocusEvent = "\x1b[?1004l"
|
||||
RequestModeFocusEvent = "\x1b[?1004$p"
|
||||
)
|
||||
|
||||
// SGR Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
||||
@ -589,24 +512,15 @@ const (
|
||||
//
|
||||
// CSI < Cb ; Cx ; Cy M
|
||||
//
|
||||
// Where Cb is the same as [NormalMouseMode], and Cx and Cy are the x and y.
|
||||
// Where Cb is the same as [ModeMouseNormal], and Cx and Cy are the x and y.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
SgrExtMouseMode = DECMode(1006)
|
||||
ModeMouseExtSgr = DECMode(1006)
|
||||
|
||||
SetSgrExtMouseMode = "\x1b[?1006h"
|
||||
ResetSgrExtMouseMode = "\x1b[?1006l"
|
||||
RequestSgrExtMouseMode = "\x1b[?1006$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SgrExtMouseMode] [SetSgrExtMouseMode],
|
||||
// [ResetSgrExtMouseMode], and [RequestSgrExtMouseMode] instead.
|
||||
const (
|
||||
MouseSgrExtMode = DECMode(1006) //nolint:revive // grouped constants
|
||||
EnableMouseSgrExt = "\x1b[?1006h"
|
||||
DisableMouseSgrExt = "\x1b[?1006l"
|
||||
RequestMouseSgrExt = "\x1b[?1006$p"
|
||||
SetModeMouseExtSgr = "\x1b[?1006h"
|
||||
ResetModeMouseExtSgr = "\x1b[?1006l"
|
||||
RequestModeMouseExtSgr = "\x1b[?1006$p"
|
||||
)
|
||||
|
||||
// UTF-8 Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
||||
@ -614,11 +528,11 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
Utf8ExtMouseMode = DECMode(1005)
|
||||
ModeMouseExtUtf8 = DECMode(1005)
|
||||
|
||||
SetUtf8ExtMouseMode = "\x1b[?1005h"
|
||||
ResetUtf8ExtMouseMode = "\x1b[?1005l"
|
||||
RequestUtf8ExtMouseMode = "\x1b[?1005$p"
|
||||
SetModeMouseExtUtf8 = "\x1b[?1005h"
|
||||
ResetModeMouseExtUtf8 = "\x1b[?1005l"
|
||||
RequestModeMouseExtUtf8 = "\x1b[?1005$p"
|
||||
)
|
||||
|
||||
// URXVT Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
||||
@ -626,25 +540,25 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
UrxvtExtMouseMode = DECMode(1015)
|
||||
ModeMouseExtUrxvt = DECMode(1015)
|
||||
|
||||
SetUrxvtExtMouseMode = "\x1b[?1015h"
|
||||
ResetUrxvtExtMouseMode = "\x1b[?1015l"
|
||||
RequestUrxvtExtMouseMode = "\x1b[?1015$p"
|
||||
SetModeMouseExtUrxvt = "\x1b[?1015h"
|
||||
ResetModeMouseExtUrxvt = "\x1b[?1015l"
|
||||
RequestModeMouseExtUrxvt = "\x1b[?1015$p"
|
||||
)
|
||||
|
||||
// SGR Pixel Extended Mouse Mode is a mode that changes the mouse tracking
|
||||
// encoding to use SGR parameters with pixel coordinates.
|
||||
//
|
||||
// This is similar to [SgrExtMouseMode], but also reports pixel coordinates.
|
||||
// This is similar to [ModeMouseExtSgr], but also reports pixel coordinates.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
const (
|
||||
SgrPixelExtMouseMode = DECMode(1016)
|
||||
ModeMouseExtSgrPixel = DECMode(1016)
|
||||
|
||||
SetSgrPixelExtMouseMode = "\x1b[?1016h"
|
||||
ResetSgrPixelExtMouseMode = "\x1b[?1016l"
|
||||
RequestSgrPixelExtMouseMode = "\x1b[?1016$p"
|
||||
SetModeMouseExtSgrPixel = "\x1b[?1016h"
|
||||
ResetModeMouseExtSgrPixel = "\x1b[?1016l"
|
||||
RequestModeMouseExtSgrPixel = "\x1b[?1016$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Mode is a mode that determines whether the alternate screen
|
||||
@ -653,11 +567,11 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||
const (
|
||||
AltScreenMode = DECMode(1047)
|
||||
ModeAltScreen = DECMode(1047)
|
||||
|
||||
SetAltScreenMode = "\x1b[?1047h"
|
||||
ResetAltScreenMode = "\x1b[?1047l"
|
||||
RequestAltScreenMode = "\x1b[?1047$p"
|
||||
SetModeAltScreen = "\x1b[?1047h"
|
||||
ResetModeAltScreen = "\x1b[?1047l"
|
||||
RequestModeAltScreen = "\x1b[?1047$p"
|
||||
)
|
||||
|
||||
// Save Cursor Mode is a mode that saves the cursor position.
|
||||
@ -665,42 +579,24 @@ const (
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||
const (
|
||||
SaveCursorMode = DECMode(1048)
|
||||
ModeSaveCursor = DECMode(1048)
|
||||
|
||||
SetSaveCursorMode = "\x1b[?1048h"
|
||||
ResetSaveCursorMode = "\x1b[?1048l"
|
||||
RequestSaveCursorMode = "\x1b[?1048$p"
|
||||
SetModeSaveCursor = "\x1b[?1048h"
|
||||
ResetModeSaveCursor = "\x1b[?1048l"
|
||||
RequestModeSaveCursor = "\x1b[?1048$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Save Cursor Mode is a mode that saves the cursor position as in
|
||||
// [SaveCursorMode], switches to the alternate screen buffer as in [AltScreenMode],
|
||||
// [ModeSaveCursor], switches to the alternate screen buffer as in [ModeAltScreen],
|
||||
// and clears the screen on switch.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||
const (
|
||||
AltScreenSaveCursorMode = DECMode(1049)
|
||||
ModeAltScreenSaveCursor = DECMode(1049)
|
||||
|
||||
SetAltScreenSaveCursorMode = "\x1b[?1049h"
|
||||
ResetAltScreenSaveCursorMode = "\x1b[?1049l"
|
||||
RequestAltScreenSaveCursorMode = "\x1b[?1049$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Buffer is a mode that determines whether the alternate screen
|
||||
// buffer is active.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||
//
|
||||
// Deprecated: use [AltScreenSaveCursorMode] instead.
|
||||
const (
|
||||
AltScreenBufferMode = DECMode(1049)
|
||||
|
||||
SetAltScreenBufferMode = "\x1b[?1049h"
|
||||
ResetAltScreenBufferMode = "\x1b[?1049l"
|
||||
RequestAltScreenBufferMode = "\x1b[?1049$p"
|
||||
|
||||
EnableAltScreenBuffer = "\x1b[?1049h"
|
||||
DisableAltScreenBuffer = "\x1b[?1049l"
|
||||
RequestAltScreenBuffer = "\x1b[?1049$p"
|
||||
SetModeAltScreenSaveCursor = "\x1b[?1049h"
|
||||
ResetModeAltScreenSaveCursor = "\x1b[?1049l"
|
||||
RequestModeAltScreenSaveCursor = "\x1b[?1049$p"
|
||||
)
|
||||
|
||||
// Bracketed Paste Mode is a mode that determines whether pasted text is
|
||||
@ -709,19 +605,11 @@ const (
|
||||
// See: https://cirw.in/blog/bracketed-paste
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
|
||||
const (
|
||||
BracketedPasteMode = DECMode(2004)
|
||||
ModeBracketedPaste = DECMode(2004)
|
||||
|
||||
SetBracketedPasteMode = "\x1b[?2004h"
|
||||
ResetBracketedPasteMode = "\x1b[?2004l"
|
||||
RequestBracketedPasteMode = "\x1b[?2004$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetBracketedPasteMode], [ResetBracketedPasteMode], and
|
||||
// [RequestBracketedPasteMode] instead.
|
||||
const (
|
||||
EnableBracketedPaste = "\x1b[?2004h" //nolint:revive // grouped constants
|
||||
DisableBracketedPaste = "\x1b[?2004l"
|
||||
RequestBracketedPaste = "\x1b[?2004$p"
|
||||
SetModeBracketedPaste = "\x1b[?2004h"
|
||||
ResetModeBracketedPaste = "\x1b[?2004l"
|
||||
RequestModeBracketedPaste = "\x1b[?2004$p"
|
||||
)
|
||||
|
||||
// Synchronized Output Mode is a mode that determines whether output is
|
||||
@ -729,23 +617,11 @@ const (
|
||||
//
|
||||
// See: https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036
|
||||
const (
|
||||
SynchronizedOutputMode = DECMode(2026)
|
||||
ModeSynchronizedOutput = DECMode(2026)
|
||||
|
||||
SetSynchronizedOutputMode = "\x1b[?2026h"
|
||||
ResetSynchronizedOutputMode = "\x1b[?2026l"
|
||||
RequestSynchronizedOutputMode = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Synchronized Output Mode. See [SynchronizedOutputMode].
|
||||
//
|
||||
// Deprecated: use [SynchronizedOutputMode], [SetSynchronizedOutputMode], and
|
||||
// [ResetSynchronizedOutputMode], and [RequestSynchronizedOutputMode] instead.
|
||||
const (
|
||||
SyncdOutputMode = DECMode(2026)
|
||||
|
||||
EnableSyncdOutput = "\x1b[?2026h"
|
||||
DisableSyncdOutput = "\x1b[?2026l"
|
||||
RequestSyncdOutput = "\x1b[?2026$p"
|
||||
SetModeSynchronizedOutput = "\x1b[?2026h"
|
||||
ResetModeSynchronizedOutput = "\x1b[?2026l"
|
||||
RequestModeSynchronizedOutput = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Unicode Core Mode is a mode that determines whether the terminal should use
|
||||
@ -754,41 +630,16 @@ const (
|
||||
//
|
||||
// See: https://github.com/contour-terminal/terminal-unicode-core
|
||||
const (
|
||||
UnicodeCoreMode = DECMode(2027)
|
||||
ModeUnicodeCore = DECMode(2027)
|
||||
|
||||
SetUnicodeCoreMode = "\x1b[?2027h"
|
||||
ResetUnicodeCoreMode = "\x1b[?2027l"
|
||||
RequestUnicodeCoreMode = "\x1b[?2027$p"
|
||||
SetModeUnicodeCore = "\x1b[?2027h"
|
||||
ResetModeUnicodeCore = "\x1b[?2027l"
|
||||
RequestModeUnicodeCore = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Grapheme Clustering Mode is a mode that determines whether the terminal
|
||||
// should look for grapheme clusters instead of single runes in the rendered
|
||||
// text. This makes the terminal properly render combining characters such as
|
||||
// emojis.
|
||||
//
|
||||
// See: https://github.com/contour-terminal/terminal-unicode-core
|
||||
//
|
||||
// Deprecated: use [GraphemeClusteringMode], [SetUnicodeCoreMode],
|
||||
// [ResetUnicodeCoreMode], and [RequestUnicodeCoreMode] instead.
|
||||
const (
|
||||
GraphemeClusteringMode = DECMode(2027)
|
||||
|
||||
SetGraphemeClusteringMode = "\x1b[?2027h"
|
||||
ResetGraphemeClusteringMode = "\x1b[?2027l"
|
||||
RequestGraphemeClusteringMode = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Grapheme Clustering Mode. See [GraphemeClusteringMode].
|
||||
//
|
||||
// Deprecated: use [SetUnicodeCoreMode], [ResetUnicodeCoreMode], and
|
||||
// [RequestUnicodeCoreMode] instead.
|
||||
const (
|
||||
EnableGraphemeClustering = "\x1b[?2027h"
|
||||
DisableGraphemeClustering = "\x1b[?2027l"
|
||||
RequestGraphemeClustering = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// LightDarkMode is a mode that enables reporting the operating system's color
|
||||
// ModeLightDark is a mode that enables reporting the operating system's color
|
||||
// scheme (light or dark) preference. It reports the color scheme as a [DSR]
|
||||
// and [LightDarkReport] escape sequences encoded as follows:
|
||||
//
|
||||
@ -802,14 +653,14 @@ const (
|
||||
//
|
||||
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
||||
const (
|
||||
LightDarkMode = DECMode(2031)
|
||||
ModeLightDark = DECMode(2031)
|
||||
|
||||
SetLightDarkMode = "\x1b[?2031h"
|
||||
ResetLightDarkMode = "\x1b[?2031l"
|
||||
RequestLightDarkMode = "\x1b[?2031$p"
|
||||
SetModeLightDark = "\x1b[?2031h"
|
||||
ResetModeLightDark = "\x1b[?2031l"
|
||||
RequestModeLightDark = "\x1b[?2031$p"
|
||||
)
|
||||
|
||||
// InBandResizeMode is a mode that reports terminal resize events as escape
|
||||
// ModeInBandResize is a mode that reports terminal resize events as escape
|
||||
// sequences. This is useful for systems that do not support [SIGWINCH] like
|
||||
// Windows.
|
||||
//
|
||||
@ -819,11 +670,11 @@ const (
|
||||
//
|
||||
// See: https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
|
||||
const (
|
||||
InBandResizeMode = DECMode(2048)
|
||||
ModeInBandResize = DECMode(2048)
|
||||
|
||||
SetInBandResizeMode = "\x1b[?2048h"
|
||||
ResetInBandResizeMode = "\x1b[?2048l"
|
||||
RequestInBandResizeMode = "\x1b[?2048$p"
|
||||
SetModeInBandResize = "\x1b[?2048h"
|
||||
ResetModeInBandResize = "\x1b[?2048l"
|
||||
RequestModeInBandResize = "\x1b[?2048$p"
|
||||
)
|
||||
|
||||
// Win32Input is a mode that determines whether input is processed by the
|
||||
@ -831,17 +682,9 @@ const (
|
||||
//
|
||||
// See: https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md
|
||||
const (
|
||||
Win32InputMode = DECMode(9001)
|
||||
ModeWin32Input = DECMode(9001)
|
||||
|
||||
SetWin32InputMode = "\x1b[?9001h"
|
||||
ResetWin32InputMode = "\x1b[?9001l"
|
||||
RequestWin32InputMode = "\x1b[?9001$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetWin32InputMode], [ResetWin32InputMode], and
|
||||
// [RequestWin32InputMode] instead.
|
||||
const (
|
||||
EnableWin32Input = "\x1b[?9001h" //nolint:revive // grouped constants
|
||||
DisableWin32Input = "\x1b[?9001l"
|
||||
RequestWin32Input = "\x1b[?9001$p"
|
||||
SetModeWin32Input = "\x1b[?9001h"
|
||||
ResetModeWin32Input = "\x1b[?9001l"
|
||||
RequestModeWin32Input = "\x1b[?9001$p"
|
||||
)
|
||||
|
||||
495
vendor/github.com/charmbracelet/x/ansi/mode_deprecated.go
generated
vendored
Normal file
495
vendor/github.com/charmbracelet/x/ansi/mode_deprecated.go
generated
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
package ansi
|
||||
|
||||
// Keyboard Action Mode (KAM) controls locking of the keyboard.
|
||||
//
|
||||
// Deprecated: use [ModeKeyboardAction] instead.
|
||||
const (
|
||||
KeyboardActionMode = ANSIMode(2)
|
||||
|
||||
SetKeyboardActionMode = "\x1b[2h"
|
||||
ResetKeyboardActionMode = "\x1b[2l"
|
||||
RequestKeyboardActionMode = "\x1b[2$p"
|
||||
)
|
||||
|
||||
// Insert/Replace Mode (IRM) determines whether characters are inserted or replaced.
|
||||
//
|
||||
// Deprecated: use [ModeInsertReplace] instead.
|
||||
const (
|
||||
InsertReplaceMode = ANSIMode(4)
|
||||
|
||||
SetInsertReplaceMode = "\x1b[4h"
|
||||
ResetInsertReplaceMode = "\x1b[4l"
|
||||
RequestInsertReplaceMode = "\x1b[4$p"
|
||||
)
|
||||
|
||||
// BiDirectional Support Mode (BDSM) determines whether the terminal supports bidirectional text.
|
||||
//
|
||||
// Deprecated: use [ModeBiDirectionalSupport] instead.
|
||||
const (
|
||||
BiDirectionalSupportMode = ANSIMode(8)
|
||||
|
||||
SetBiDirectionalSupportMode = "\x1b[8h"
|
||||
ResetBiDirectionalSupportMode = "\x1b[8l"
|
||||
RequestBiDirectionalSupportMode = "\x1b[8$p"
|
||||
)
|
||||
|
||||
// Send Receive Mode (SRM) or Local Echo Mode determines whether the terminal echoes characters.
|
||||
//
|
||||
// Deprecated: use [ModeSendReceive] instead.
|
||||
const (
|
||||
SendReceiveMode = ANSIMode(12)
|
||||
LocalEchoMode = SendReceiveMode
|
||||
|
||||
SetSendReceiveMode = "\x1b[12h"
|
||||
ResetSendReceiveMode = "\x1b[12l"
|
||||
RequestSendReceiveMode = "\x1b[12$p"
|
||||
|
||||
SetLocalEchoMode = "\x1b[12h"
|
||||
ResetLocalEchoMode = "\x1b[12l"
|
||||
RequestLocalEchoMode = "\x1b[12$p"
|
||||
)
|
||||
|
||||
// Line Feed/New Line Mode (LNM) determines whether the terminal interprets line feed as new line.
|
||||
//
|
||||
// Deprecated: use [ModeLineFeedNewLine] instead.
|
||||
const (
|
||||
LineFeedNewLineMode = ANSIMode(20)
|
||||
|
||||
SetLineFeedNewLineMode = "\x1b[20h"
|
||||
ResetLineFeedNewLineMode = "\x1b[20l"
|
||||
RequestLineFeedNewLineMode = "\x1b[20$p"
|
||||
)
|
||||
|
||||
// Cursor Keys Mode (DECCKM) determines whether cursor keys send ANSI or application sequences.
|
||||
//
|
||||
// Deprecated: use [ModeCursorKeys] instead.
|
||||
const (
|
||||
CursorKeysMode = DECMode(1)
|
||||
|
||||
SetCursorKeysMode = "\x1b[?1h"
|
||||
ResetCursorKeysMode = "\x1b[?1l"
|
||||
RequestCursorKeysMode = "\x1b[?1$p"
|
||||
)
|
||||
|
||||
// Cursor Keys mode.
|
||||
//
|
||||
// Deprecated: use [SetModeCursorKeys] and [ResetModeCursorKeys] instead.
|
||||
const (
|
||||
EnableCursorKeys = "\x1b[?1h"
|
||||
DisableCursorKeys = "\x1b[?1l"
|
||||
)
|
||||
|
||||
// Origin Mode (DECOM) determines whether the cursor moves to home or margin position.
|
||||
//
|
||||
// Deprecated: use [ModeOrigin] instead.
|
||||
const (
|
||||
OriginMode = DECMode(6)
|
||||
|
||||
SetOriginMode = "\x1b[?6h"
|
||||
ResetOriginMode = "\x1b[?6l"
|
||||
RequestOriginMode = "\x1b[?6$p"
|
||||
)
|
||||
|
||||
// Auto Wrap Mode (DECAWM) determines whether the cursor wraps to the next line.
|
||||
//
|
||||
// Deprecated: use [ModeAutoWrap] instead.
|
||||
const (
|
||||
AutoWrapMode = DECMode(7)
|
||||
|
||||
SetAutoWrapMode = "\x1b[?7h"
|
||||
ResetAutoWrapMode = "\x1b[?7l"
|
||||
RequestAutoWrapMode = "\x1b[?7$p"
|
||||
)
|
||||
|
||||
// X10 Mouse Mode determines whether the mouse reports on button presses.
|
||||
//
|
||||
// Deprecated: use [ModeMouseX10] instead.
|
||||
const (
|
||||
X10MouseMode = DECMode(9)
|
||||
|
||||
SetX10MouseMode = "\x1b[?9h"
|
||||
ResetX10MouseMode = "\x1b[?9l"
|
||||
RequestX10MouseMode = "\x1b[?9$p"
|
||||
)
|
||||
|
||||
// Text Cursor Enable Mode (DECTCEM) shows/hides the cursor.
|
||||
//
|
||||
// Deprecated: use [ModeTextCursorEnable] instead.
|
||||
const (
|
||||
TextCursorEnableMode = DECMode(25)
|
||||
|
||||
SetTextCursorEnableMode = "\x1b[?25h"
|
||||
ResetTextCursorEnableMode = "\x1b[?25l"
|
||||
RequestTextCursorEnableMode = "\x1b[?25$p"
|
||||
)
|
||||
|
||||
// Text Cursor Enable mode.
|
||||
//
|
||||
// Deprecated: use [SetModeTextCursorEnable] and [ResetModeTextCursorEnable] instead.
|
||||
const (
|
||||
CursorEnableMode = DECMode(25)
|
||||
RequestCursorVisibility = "\x1b[?25$p"
|
||||
)
|
||||
|
||||
// Numeric Keypad Mode (DECNKM) determines whether the keypad sends application or numeric sequences.
|
||||
//
|
||||
// Deprecated: use [ModeNumericKeypad] instead.
|
||||
const (
|
||||
NumericKeypadMode = DECMode(66)
|
||||
|
||||
SetNumericKeypadMode = "\x1b[?66h"
|
||||
ResetNumericKeypadMode = "\x1b[?66l"
|
||||
RequestNumericKeypadMode = "\x1b[?66$p"
|
||||
)
|
||||
|
||||
// Backarrow Key Mode (DECBKM) determines whether the backspace key sends backspace or delete.
|
||||
//
|
||||
// Deprecated: use [ModeBackarrowKey] instead.
|
||||
const (
|
||||
BackarrowKeyMode = DECMode(67)
|
||||
|
||||
SetBackarrowKeyMode = "\x1b[?67h"
|
||||
ResetBackarrowKeyMode = "\x1b[?67l"
|
||||
RequestBackarrowKeyMode = "\x1b[?67$p"
|
||||
)
|
||||
|
||||
// Left Right Margin Mode (DECLRMM) determines whether left and right margins can be set.
|
||||
//
|
||||
// Deprecated: use [ModeLeftRightMargin] instead.
|
||||
const (
|
||||
LeftRightMarginMode = DECMode(69)
|
||||
|
||||
SetLeftRightMarginMode = "\x1b[?69h"
|
||||
ResetLeftRightMarginMode = "\x1b[?69l"
|
||||
RequestLeftRightMarginMode = "\x1b[?69$p"
|
||||
)
|
||||
|
||||
// Normal Mouse Mode determines whether the mouse reports on button presses and releases.
|
||||
//
|
||||
// Deprecated: use [ModeMouseNormal] instead.
|
||||
const (
|
||||
NormalMouseMode = DECMode(1000)
|
||||
|
||||
SetNormalMouseMode = "\x1b[?1000h"
|
||||
ResetNormalMouseMode = "\x1b[?1000l"
|
||||
RequestNormalMouseMode = "\x1b[?1000$p"
|
||||
)
|
||||
|
||||
// VT Mouse Tracking mode.
|
||||
//
|
||||
// Deprecated: use [ModeMouseNormal] instead.
|
||||
const (
|
||||
MouseMode = DECMode(1000)
|
||||
|
||||
EnableMouse = "\x1b[?1000h"
|
||||
DisableMouse = "\x1b[?1000l"
|
||||
RequestMouse = "\x1b[?1000$p"
|
||||
)
|
||||
|
||||
// Highlight Mouse Tracking determines whether the mouse reports on button presses and highlighted cells.
|
||||
//
|
||||
// Deprecated: use [ModeMouseHighlight] instead.
|
||||
const (
|
||||
HighlightMouseMode = DECMode(1001)
|
||||
|
||||
SetHighlightMouseMode = "\x1b[?1001h"
|
||||
ResetHighlightMouseMode = "\x1b[?1001l"
|
||||
RequestHighlightMouseMode = "\x1b[?1001$p"
|
||||
)
|
||||
|
||||
// VT Hilite Mouse Tracking mode.
|
||||
//
|
||||
// Deprecated: use [ModeMouseHighlight] instead.
|
||||
const (
|
||||
MouseHiliteMode = DECMode(1001)
|
||||
|
||||
EnableMouseHilite = "\x1b[?1001h"
|
||||
DisableMouseHilite = "\x1b[?1001l"
|
||||
RequestMouseHilite = "\x1b[?1001$p"
|
||||
)
|
||||
|
||||
// Button Event Mouse Tracking reports button-motion events when a button is pressed.
|
||||
//
|
||||
// Deprecated: use [ModeMouseButtonEvent] instead.
|
||||
const (
|
||||
ButtonEventMouseMode = DECMode(1002)
|
||||
|
||||
SetButtonEventMouseMode = "\x1b[?1002h"
|
||||
ResetButtonEventMouseMode = "\x1b[?1002l"
|
||||
RequestButtonEventMouseMode = "\x1b[?1002$p"
|
||||
)
|
||||
|
||||
// Cell Motion Mouse Tracking mode.
|
||||
//
|
||||
// Deprecated: use [ModeMouseButtonEvent] instead.
|
||||
const (
|
||||
MouseCellMotionMode = DECMode(1002)
|
||||
|
||||
EnableMouseCellMotion = "\x1b[?1002h"
|
||||
DisableMouseCellMotion = "\x1b[?1002l"
|
||||
RequestMouseCellMotion = "\x1b[?1002$p"
|
||||
)
|
||||
|
||||
// Any Event Mouse Tracking reports all motion events.
|
||||
//
|
||||
// Deprecated: use [ModeMouseAnyEvent] instead.
|
||||
const (
|
||||
AnyEventMouseMode = DECMode(1003)
|
||||
|
||||
SetAnyEventMouseMode = "\x1b[?1003h"
|
||||
ResetAnyEventMouseMode = "\x1b[?1003l"
|
||||
RequestAnyEventMouseMode = "\x1b[?1003$p"
|
||||
)
|
||||
|
||||
// All Mouse Tracking mode.
|
||||
//
|
||||
// Deprecated: use [ModeMouseAnyEvent] instead.
|
||||
const (
|
||||
MouseAllMotionMode = DECMode(1003)
|
||||
|
||||
EnableMouseAllMotion = "\x1b[?1003h"
|
||||
DisableMouseAllMotion = "\x1b[?1003l"
|
||||
RequestMouseAllMotion = "\x1b[?1003$p"
|
||||
)
|
||||
|
||||
// Focus Event Mode determines whether the terminal reports focus and blur events.
|
||||
//
|
||||
// Deprecated: use [ModeFocusEvent] instead.
|
||||
const (
|
||||
FocusEventMode = DECMode(1004)
|
||||
|
||||
SetFocusEventMode = "\x1b[?1004h"
|
||||
ResetFocusEventMode = "\x1b[?1004l"
|
||||
RequestFocusEventMode = "\x1b[?1004$p"
|
||||
)
|
||||
|
||||
// Focus reporting mode.
|
||||
//
|
||||
// Deprecated: use [SetModeFocusEvent], [ResetModeFocusEvent], and
|
||||
// [RequestModeFocusEvent] instead.
|
||||
const (
|
||||
ReportFocusMode = DECMode(1004)
|
||||
|
||||
EnableReportFocus = "\x1b[?1004h"
|
||||
DisableReportFocus = "\x1b[?1004l"
|
||||
RequestReportFocus = "\x1b[?1004$p"
|
||||
)
|
||||
|
||||
// UTF-8 Extended Mouse Mode changes the mouse tracking encoding to use UTF-8 parameters.
|
||||
//
|
||||
// Deprecated: use [ModeMouseExtUtf8] instead.
|
||||
const (
|
||||
Utf8ExtMouseMode = DECMode(1005)
|
||||
|
||||
SetUtf8ExtMouseMode = "\x1b[?1005h"
|
||||
ResetUtf8ExtMouseMode = "\x1b[?1005l"
|
||||
RequestUtf8ExtMouseMode = "\x1b[?1005$p"
|
||||
)
|
||||
|
||||
// SGR Extended Mouse Mode changes the mouse tracking encoding to use SGR parameters.
|
||||
//
|
||||
// Deprecated: use [ModeMouseExtSgr] instead.
|
||||
const (
|
||||
SgrExtMouseMode = DECMode(1006)
|
||||
|
||||
SetSgrExtMouseMode = "\x1b[?1006h"
|
||||
ResetSgrExtMouseMode = "\x1b[?1006l"
|
||||
RequestSgrExtMouseMode = "\x1b[?1006$p"
|
||||
)
|
||||
|
||||
// Mouse SGR Extended mode.
|
||||
//
|
||||
// Deprecated: use [ModeMouseExtSgr], [SetModeMouseExtSgr],
|
||||
// [ResetModeMouseExtSgr], and [RequestModeMouseExtSgr] instead.
|
||||
const (
|
||||
MouseSgrExtMode = DECMode(1006)
|
||||
EnableMouseSgrExt = "\x1b[?1006h"
|
||||
DisableMouseSgrExt = "\x1b[?1006l"
|
||||
RequestMouseSgrExt = "\x1b[?1006$p"
|
||||
)
|
||||
|
||||
// URXVT Extended Mouse Mode changes the mouse tracking encoding to use an alternate encoding.
|
||||
//
|
||||
// Deprecated: use [ModeMouseUrxvtExt] instead.
|
||||
const (
|
||||
UrxvtExtMouseMode = DECMode(1015)
|
||||
|
||||
SetUrxvtExtMouseMode = "\x1b[?1015h"
|
||||
ResetUrxvtExtMouseMode = "\x1b[?1015l"
|
||||
RequestUrxvtExtMouseMode = "\x1b[?1015$p"
|
||||
)
|
||||
|
||||
// SGR Pixel Extended Mouse Mode changes the mouse tracking encoding to use SGR parameters with pixel coordinates.
|
||||
//
|
||||
// Deprecated: use [ModeMouseExtSgrPixel] instead.
|
||||
const (
|
||||
SgrPixelExtMouseMode = DECMode(1016)
|
||||
|
||||
SetSgrPixelExtMouseMode = "\x1b[?1016h"
|
||||
ResetSgrPixelExtMouseMode = "\x1b[?1016l"
|
||||
RequestSgrPixelExtMouseMode = "\x1b[?1016$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Mode determines whether the alternate screen buffer is active.
|
||||
//
|
||||
// Deprecated: use [ModeAltScreen] instead.
|
||||
const (
|
||||
AltScreenMode = DECMode(1047)
|
||||
|
||||
SetAltScreenMode = "\x1b[?1047h"
|
||||
ResetAltScreenMode = "\x1b[?1047l"
|
||||
RequestAltScreenMode = "\x1b[?1047$p"
|
||||
)
|
||||
|
||||
// Save Cursor Mode saves the cursor position.
|
||||
//
|
||||
// Deprecated: use [ModeSaveCursor] instead.
|
||||
const (
|
||||
SaveCursorMode = DECMode(1048)
|
||||
|
||||
SetSaveCursorMode = "\x1b[?1048h"
|
||||
ResetSaveCursorMode = "\x1b[?1048l"
|
||||
RequestSaveCursorMode = "\x1b[?1048$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Save Cursor Mode saves the cursor position and switches to alternate screen.
|
||||
//
|
||||
// Deprecated: use [ModeAltScreenSaveCursor] instead.
|
||||
const (
|
||||
AltScreenSaveCursorMode = DECMode(1049)
|
||||
|
||||
SetAltScreenSaveCursorMode = "\x1b[?1049h"
|
||||
ResetAltScreenSaveCursorMode = "\x1b[?1049l"
|
||||
RequestAltScreenSaveCursorMode = "\x1b[?1049$p"
|
||||
)
|
||||
|
||||
// Alternate Screen Buffer mode.
|
||||
//
|
||||
// Deprecated: use [ModeAltScreenSaveCursor] instead.
|
||||
const (
|
||||
AltScreenBufferMode = DECMode(1049)
|
||||
|
||||
SetAltScreenBufferMode = "\x1b[?1049h"
|
||||
ResetAltScreenBufferMode = "\x1b[?1049l"
|
||||
RequestAltScreenBufferMode = "\x1b[?1049$p"
|
||||
|
||||
EnableAltScreenBuffer = "\x1b[?1049h"
|
||||
DisableAltScreenBuffer = "\x1b[?1049l"
|
||||
RequestAltScreenBuffer = "\x1b[?1049$p"
|
||||
)
|
||||
|
||||
// Bracketed Paste Mode determines whether pasted text is bracketed with escape sequences.
|
||||
//
|
||||
// Deprecated: use [ModeBracketedPaste] instead.
|
||||
const (
|
||||
BracketedPasteMode = DECMode(2004)
|
||||
|
||||
SetBracketedPasteMode = "\x1b[?2004h"
|
||||
ResetBracketedPasteMode = "\x1b[?2004l"
|
||||
RequestBracketedPasteMode = "\x1b[?2004$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetModeBracketedPaste], [ResetModeBracketedPaste], and
|
||||
// [RequestModeBracketedPaste] instead.
|
||||
const (
|
||||
EnableBracketedPaste = "\x1b[?2004h" //nolint:revive
|
||||
DisableBracketedPaste = "\x1b[?2004l"
|
||||
RequestBracketedPaste = "\x1b[?2004$p"
|
||||
)
|
||||
|
||||
// Synchronized Output Mode determines whether output is synchronized with the terminal.
|
||||
//
|
||||
// Deprecated: use [ModeSynchronizedOutput] instead.
|
||||
const (
|
||||
SynchronizedOutputMode = DECMode(2026)
|
||||
|
||||
SetSynchronizedOutputMode = "\x1b[?2026h"
|
||||
ResetSynchronizedOutputMode = "\x1b[?2026l"
|
||||
RequestSynchronizedOutputMode = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Synchronized output mode.
|
||||
//
|
||||
// Deprecated: use [ModeSynchronizedOutput], [SetModeSynchronizedOutput],
|
||||
// [ResetModeSynchronizedOutput], and [RequestModeSynchronizedOutput] instead.
|
||||
const (
|
||||
SyncdOutputMode = DECMode(2026)
|
||||
|
||||
EnableSyncdOutput = "\x1b[?2026h"
|
||||
DisableSyncdOutput = "\x1b[?2026l"
|
||||
RequestSyncdOutput = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Unicode Core Mode determines whether the terminal uses Unicode grapheme clustering.
|
||||
//
|
||||
// Deprecated: use [ModeUnicodeCore] instead.
|
||||
const (
|
||||
UnicodeCoreMode = DECMode(2027)
|
||||
|
||||
SetUnicodeCoreMode = "\x1b[?2027h"
|
||||
ResetUnicodeCoreMode = "\x1b[?2027l"
|
||||
RequestUnicodeCoreMode = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Grapheme Clustering Mode determines whether the terminal looks for grapheme clusters.
|
||||
//
|
||||
// Deprecated: use [ModeUnicodeCore], [SetModeUnicodeCore],
|
||||
// [ResetModeUnicodeCore], and [RequestModeUnicodeCore] instead.
|
||||
const (
|
||||
GraphemeClusteringMode = DECMode(2027)
|
||||
|
||||
SetGraphemeClusteringMode = "\x1b[?2027h"
|
||||
ResetGraphemeClusteringMode = "\x1b[?2027l"
|
||||
RequestGraphemeClusteringMode = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Unicode Core mode.
|
||||
//
|
||||
// Deprecated: use [SetModeUnicodeCore], [ResetModeUnicodeCore], and
|
||||
// [RequestModeUnicodeCore] instead.
|
||||
const (
|
||||
EnableGraphemeClustering = "\x1b[?2027h"
|
||||
DisableGraphemeClustering = "\x1b[?2027l"
|
||||
RequestGraphemeClustering = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Light Dark Mode enables reporting the operating system's color scheme preference.
|
||||
//
|
||||
// Deprecated: use [ModeLightDark] instead.
|
||||
const (
|
||||
LightDarkMode = DECMode(2031)
|
||||
|
||||
SetLightDarkMode = "\x1b[?2031h"
|
||||
ResetLightDarkMode = "\x1b[?2031l"
|
||||
RequestLightDarkMode = "\x1b[?2031$p"
|
||||
)
|
||||
|
||||
// In Band Resize Mode reports terminal resize events as escape sequences.
|
||||
//
|
||||
// Deprecated: use [ModeInBandResize] instead.
|
||||
const (
|
||||
InBandResizeMode = DECMode(2048)
|
||||
|
||||
SetInBandResizeMode = "\x1b[?2048h"
|
||||
ResetInBandResizeMode = "\x1b[?2048l"
|
||||
RequestInBandResizeMode = "\x1b[?2048$p"
|
||||
)
|
||||
|
||||
// Win32Input determines whether input is processed by the Win32 console and Conpty.
|
||||
//
|
||||
// Deprecated: use [ModeWin32Input] instead.
|
||||
const (
|
||||
Win32InputMode = DECMode(9001)
|
||||
|
||||
SetWin32InputMode = "\x1b[?9001h"
|
||||
ResetWin32InputMode = "\x1b[?9001l"
|
||||
RequestWin32InputMode = "\x1b[?9001$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetModeWin32Input], [ResetModeWin32Input], and
|
||||
// [RequestModeWin32Input] instead.
|
||||
const (
|
||||
EnableWin32Input = "\x1b[?9001h" //nolint:revive
|
||||
DisableWin32Input = "\x1b[?9001l"
|
||||
RequestWin32Input = "\x1b[?9001$p"
|
||||
)
|
||||
2
vendor/github.com/charmbracelet/x/ansi/mouse.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/mouse.go
generated
vendored
@ -134,7 +134,7 @@ func EncodeMouseButton(b MouseButton, motion, shift, alt, ctrl bool) (m byte) {
|
||||
m |= bitMotion
|
||||
}
|
||||
|
||||
return //nolint:nakedret
|
||||
return m
|
||||
}
|
||||
|
||||
// x10Offset is the offset for X10 mouse events.
|
||||
|
||||
19
vendor/github.com/charmbracelet/x/ansi/notification.go
generated
vendored
19
vendor/github.com/charmbracelet/x/ansi/notification.go
generated
vendored
@ -1,5 +1,10 @@
|
||||
package ansi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Notify sends a desktop notification using iTerm's OSC 9.
|
||||
//
|
||||
// OSC 9 ; Mc ST
|
||||
@ -11,3 +16,17 @@ package ansi
|
||||
func Notify(s string) string {
|
||||
return "\x1b]9;" + s + "\x07"
|
||||
}
|
||||
|
||||
// DesktopNotification sends a desktop notification based on the extensible OSC
|
||||
// 99 escape code.
|
||||
//
|
||||
// OSC 99 ; <metadata> ; <payload> ST
|
||||
// OSC 99 ; <metadata> ; <payload> BEL
|
||||
//
|
||||
// Where <metadata> is a colon-separated list of key-value pairs, and
|
||||
// <payload> is the notification body.
|
||||
//
|
||||
// See: https://sw.kovidgoyal.net/kitty/desktop-notifications/
|
||||
func DesktopNotification(payload string, metadata ...string) string {
|
||||
return fmt.Sprintf("\x1b]99;%s;%s\x07", strings.Join(metadata, ":"), payload)
|
||||
}
|
||||
|
||||
33
vendor/github.com/charmbracelet/x/ansi/parser_decode.go
generated
vendored
33
vendor/github.com/charmbracelet/x/ansi/parser_decode.go
generated
vendored
@ -4,8 +4,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/charmbracelet/x/ansi/parser"
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/rivo/uniseg"
|
||||
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||
)
|
||||
|
||||
// State represents the state of the ANSI escape sequence parser used by
|
||||
@ -176,10 +175,7 @@ func decodeSequence[T string | []byte](m Method, b T, state State, p *Parser) (s
|
||||
}
|
||||
|
||||
if utf8.RuneStart(c) {
|
||||
seq, _, width, _ = FirstGraphemeCluster(b, -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(seq))
|
||||
}
|
||||
seq, width = FirstGraphemeCluster(b, m)
|
||||
i += len(seq)
|
||||
return b[:i], width, i, NormalState
|
||||
}
|
||||
@ -434,17 +430,22 @@ func HasEscPrefix[T string | []byte](b T) bool {
|
||||
return len(b) > 0 && b[0] == ESC
|
||||
}
|
||||
|
||||
// FirstGraphemeCluster returns the first grapheme cluster in the given string or byte slice.
|
||||
// This is a syntactic sugar function that wraps
|
||||
// uniseg.FirstGraphemeClusterInString and uniseg.FirstGraphemeCluster.
|
||||
func FirstGraphemeCluster[T string | []byte](b T, state int) (T, T, int, int) {
|
||||
// FirstGraphemeCluster returns the first grapheme cluster in the given string
|
||||
// or byte slice, and its monospace display width.
|
||||
func FirstGraphemeCluster[T string | []byte](b T, m Method) (T, int) {
|
||||
switch b := any(b).(type) {
|
||||
case string:
|
||||
cluster, rest, width, newState := uniseg.FirstGraphemeClusterInString(b, state)
|
||||
return T(cluster), T(rest), width, newState
|
||||
cluster := graphemes.FromString(b).First()
|
||||
if m == WcWidth {
|
||||
return T(cluster), wcOptions.StringWidth(cluster)
|
||||
}
|
||||
return T(cluster), dwOptions.String(cluster)
|
||||
case []byte:
|
||||
cluster, rest, width, newState := uniseg.FirstGraphemeCluster(b, state)
|
||||
return T(cluster), T(rest), width, newState
|
||||
cluster := graphemes.FromBytes(b).First()
|
||||
if m == WcWidth {
|
||||
return T(cluster), wcOptions.StringWidth(string(cluster))
|
||||
}
|
||||
return T(cluster), dwOptions.Bytes(cluster)
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
@ -490,7 +491,7 @@ func Command(prefix, inter, final byte) (c int) {
|
||||
c = int(final)
|
||||
c |= int(prefix) << parser.PrefixShift
|
||||
c |= int(inter) << parser.IntermedShift
|
||||
return
|
||||
return c
|
||||
}
|
||||
|
||||
// Param represents a sequence parameter. Sequence parameters with
|
||||
@ -520,5 +521,5 @@ func Parameter(p int, hasMore bool) (s int) {
|
||||
if hasMore {
|
||||
s |= parser.HasMoreFlag
|
||||
}
|
||||
return
|
||||
return s
|
||||
}
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/ansi/parser_sync.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/parser_sync.go
generated
vendored
@ -10,7 +10,7 @@ var parserPool = sync.Pool{
|
||||
New: func() any {
|
||||
p := NewParser()
|
||||
p.SetParamsSize(parser.MaxParamsSize)
|
||||
p.SetDataSize(1024 * 1024 * 4) // 4MB of data buffer
|
||||
p.SetDataSize(1024 * 4) // 4KB of data buffer
|
||||
return p
|
||||
},
|
||||
}
|
||||
|
||||
110
vendor/github.com/charmbracelet/x/ansi/sgr.go
generated
vendored
110
vendor/github.com/charmbracelet/x/ansi/sgr.go
generated
vendored
@ -21,59 +21,59 @@ func SGR(ps ...Attr) string {
|
||||
}
|
||||
|
||||
var attrStrings = map[int]string{
|
||||
ResetAttr: resetAttr,
|
||||
BoldAttr: boldAttr,
|
||||
FaintAttr: faintAttr,
|
||||
ItalicAttr: italicAttr,
|
||||
UnderlineAttr: underlineAttr,
|
||||
SlowBlinkAttr: slowBlinkAttr,
|
||||
RapidBlinkAttr: rapidBlinkAttr,
|
||||
ReverseAttr: reverseAttr,
|
||||
ConcealAttr: concealAttr,
|
||||
StrikethroughAttr: strikethroughAttr,
|
||||
NormalIntensityAttr: normalIntensityAttr,
|
||||
NoItalicAttr: noItalicAttr,
|
||||
NoUnderlineAttr: noUnderlineAttr,
|
||||
NoBlinkAttr: noBlinkAttr,
|
||||
NoReverseAttr: noReverseAttr,
|
||||
NoConcealAttr: noConcealAttr,
|
||||
NoStrikethroughAttr: noStrikethroughAttr,
|
||||
BlackForegroundColorAttr: blackForegroundColorAttr,
|
||||
RedForegroundColorAttr: redForegroundColorAttr,
|
||||
GreenForegroundColorAttr: greenForegroundColorAttr,
|
||||
YellowForegroundColorAttr: yellowForegroundColorAttr,
|
||||
BlueForegroundColorAttr: blueForegroundColorAttr,
|
||||
MagentaForegroundColorAttr: magentaForegroundColorAttr,
|
||||
CyanForegroundColorAttr: cyanForegroundColorAttr,
|
||||
WhiteForegroundColorAttr: whiteForegroundColorAttr,
|
||||
ExtendedForegroundColorAttr: extendedForegroundColorAttr,
|
||||
DefaultForegroundColorAttr: defaultForegroundColorAttr,
|
||||
BlackBackgroundColorAttr: blackBackgroundColorAttr,
|
||||
RedBackgroundColorAttr: redBackgroundColorAttr,
|
||||
GreenBackgroundColorAttr: greenBackgroundColorAttr,
|
||||
YellowBackgroundColorAttr: yellowBackgroundColorAttr,
|
||||
BlueBackgroundColorAttr: blueBackgroundColorAttr,
|
||||
MagentaBackgroundColorAttr: magentaBackgroundColorAttr,
|
||||
CyanBackgroundColorAttr: cyanBackgroundColorAttr,
|
||||
WhiteBackgroundColorAttr: whiteBackgroundColorAttr,
|
||||
ExtendedBackgroundColorAttr: extendedBackgroundColorAttr,
|
||||
DefaultBackgroundColorAttr: defaultBackgroundColorAttr,
|
||||
ExtendedUnderlineColorAttr: extendedUnderlineColorAttr,
|
||||
DefaultUnderlineColorAttr: defaultUnderlineColorAttr,
|
||||
BrightBlackForegroundColorAttr: brightBlackForegroundColorAttr,
|
||||
BrightRedForegroundColorAttr: brightRedForegroundColorAttr,
|
||||
BrightGreenForegroundColorAttr: brightGreenForegroundColorAttr,
|
||||
BrightYellowForegroundColorAttr: brightYellowForegroundColorAttr,
|
||||
BrightBlueForegroundColorAttr: brightBlueForegroundColorAttr,
|
||||
BrightMagentaForegroundColorAttr: brightMagentaForegroundColorAttr,
|
||||
BrightCyanForegroundColorAttr: brightCyanForegroundColorAttr,
|
||||
BrightWhiteForegroundColorAttr: brightWhiteForegroundColorAttr,
|
||||
BrightBlackBackgroundColorAttr: brightBlackBackgroundColorAttr,
|
||||
BrightRedBackgroundColorAttr: brightRedBackgroundColorAttr,
|
||||
BrightGreenBackgroundColorAttr: brightGreenBackgroundColorAttr,
|
||||
BrightYellowBackgroundColorAttr: brightYellowBackgroundColorAttr,
|
||||
BrightBlueBackgroundColorAttr: brightBlueBackgroundColorAttr,
|
||||
BrightMagentaBackgroundColorAttr: brightMagentaBackgroundColorAttr,
|
||||
BrightCyanBackgroundColorAttr: brightCyanBackgroundColorAttr,
|
||||
BrightWhiteBackgroundColorAttr: brightWhiteBackgroundColorAttr,
|
||||
AttrReset: attrReset,
|
||||
AttrBold: attrBold,
|
||||
AttrFaint: attrFaint,
|
||||
AttrItalic: attrItalic,
|
||||
AttrUnderline: attrUnderline,
|
||||
AttrBlink: attrBlink,
|
||||
AttrRapidBlink: attrRapidBlink,
|
||||
AttrReverse: attrReverse,
|
||||
AttrConceal: attrConceal,
|
||||
AttrStrikethrough: attrStrikethrough,
|
||||
AttrNormalIntensity: attrNormalIntensity,
|
||||
AttrNoItalic: attrNoItalic,
|
||||
AttrNoUnderline: attrNoUnderline,
|
||||
AttrNoBlink: attrNoBlink,
|
||||
AttrNoReverse: attrNoReverse,
|
||||
AttrNoConceal: attrNoConceal,
|
||||
AttrNoStrikethrough: attrNoStrikethrough,
|
||||
AttrBlackForegroundColor: attrBlackForegroundColor,
|
||||
AttrRedForegroundColor: attrRedForegroundColor,
|
||||
AttrGreenForegroundColor: attrGreenForegroundColor,
|
||||
AttrYellowForegroundColor: attrYellowForegroundColor,
|
||||
AttrBlueForegroundColor: attrBlueForegroundColor,
|
||||
AttrMagentaForegroundColor: attrMagentaForegroundColor,
|
||||
AttrCyanForegroundColor: attrCyanForegroundColor,
|
||||
AttrWhiteForegroundColor: attrWhiteForegroundColor,
|
||||
AttrExtendedForegroundColor: attrExtendedForegroundColor,
|
||||
AttrDefaultForegroundColor: attrDefaultForegroundColor,
|
||||
AttrBlackBackgroundColor: attrBlackBackgroundColor,
|
||||
AttrRedBackgroundColor: attrRedBackgroundColor,
|
||||
AttrGreenBackgroundColor: attrGreenBackgroundColor,
|
||||
AttrYellowBackgroundColor: attrYellowBackgroundColor,
|
||||
AttrBlueBackgroundColor: attrBlueBackgroundColor,
|
||||
AttrMagentaBackgroundColor: attrMagentaBackgroundColor,
|
||||
AttrCyanBackgroundColor: attrCyanBackgroundColor,
|
||||
AttrWhiteBackgroundColor: attrWhiteBackgroundColor,
|
||||
AttrExtendedBackgroundColor: attrExtendedBackgroundColor,
|
||||
AttrDefaultBackgroundColor: attrDefaultBackgroundColor,
|
||||
AttrExtendedUnderlineColor: attrExtendedUnderlineColor,
|
||||
AttrDefaultUnderlineColor: attrDefaultUnderlineColor,
|
||||
AttrBrightBlackForegroundColor: attrBrightBlackForegroundColor,
|
||||
AttrBrightRedForegroundColor: attrBrightRedForegroundColor,
|
||||
AttrBrightGreenForegroundColor: attrBrightGreenForegroundColor,
|
||||
AttrBrightYellowForegroundColor: attrBrightYellowForegroundColor,
|
||||
AttrBrightBlueForegroundColor: attrBrightBlueForegroundColor,
|
||||
AttrBrightMagentaForegroundColor: attrBrightMagentaForegroundColor,
|
||||
AttrBrightCyanForegroundColor: attrBrightCyanForegroundColor,
|
||||
AttrBrightWhiteForegroundColor: attrBrightWhiteForegroundColor,
|
||||
AttrBrightBlackBackgroundColor: attrBrightBlackBackgroundColor,
|
||||
AttrBrightRedBackgroundColor: attrBrightRedBackgroundColor,
|
||||
AttrBrightGreenBackgroundColor: attrBrightGreenBackgroundColor,
|
||||
AttrBrightYellowBackgroundColor: attrBrightYellowBackgroundColor,
|
||||
AttrBrightBlueBackgroundColor: attrBrightBlueBackgroundColor,
|
||||
AttrBrightMagentaBackgroundColor: attrBrightMagentaBackgroundColor,
|
||||
AttrBrightCyanBackgroundColor: attrBrightCyanBackgroundColor,
|
||||
AttrBrightWhiteBackgroundColor: attrBrightWhiteBackgroundColor,
|
||||
}
|
||||
|
||||
630
vendor/github.com/charmbracelet/x/ansi/style.go
generated
vendored
630
vendor/github.com/charmbracelet/x/ansi/style.go
generated
vendored
@ -17,7 +17,9 @@ type Attr = int
|
||||
// Style represents an ANSI SGR (Select Graphic Rendition) style.
|
||||
type Style []string
|
||||
|
||||
// NewStyle returns a new style with the given attributes.
|
||||
// NewStyle returns a new style with the given attributes. Attributes are SGR
|
||||
// (Select Graphic Rendition) codes that control text formatting like bold,
|
||||
// italic, colors, etc.
|
||||
func NewStyle(attrs ...Attr) Style {
|
||||
if len(attrs) == 0 {
|
||||
return Style{}
|
||||
@ -46,7 +48,8 @@ func (s Style) String() string {
|
||||
return "\x1b[" + strings.Join(s, ";") + "m"
|
||||
}
|
||||
|
||||
// Styled returns a styled string with the given style applied.
|
||||
// Styled returns a styled string with the given style applied. The style is
|
||||
// applied at the beginning and reset at the end of the string.
|
||||
func (s Style) Styled(str string) string {
|
||||
if len(s) == 0 {
|
||||
return str
|
||||
@ -54,309 +57,446 @@ func (s Style) Styled(str string) string {
|
||||
return s.String() + str + ResetStyle
|
||||
}
|
||||
|
||||
// Reset appends the reset style attribute to the style.
|
||||
// Reset appends the reset style attribute to the style. This resets all
|
||||
// formatting attributes to their defaults.
|
||||
func (s Style) Reset() Style {
|
||||
return append(s, resetAttr)
|
||||
return append(s, attrReset)
|
||||
}
|
||||
|
||||
// Bold appends the bold style attribute to the style.
|
||||
// Bold appends the bold or normal intensity style attribute to the style.
|
||||
// You can use [Style.Normal] to reset to normal intensity.
|
||||
func (s Style) Bold() Style {
|
||||
return append(s, boldAttr)
|
||||
return append(s, attrBold)
|
||||
}
|
||||
|
||||
// Faint appends the faint style attribute to the style.
|
||||
// Faint appends the faint or normal intensity style attribute to the style.
|
||||
// You can use [Style.Normal] to reset to normal intensity.
|
||||
func (s Style) Faint() Style {
|
||||
return append(s, faintAttr)
|
||||
return append(s, attrFaint)
|
||||
}
|
||||
|
||||
// Italic appends the italic style attribute to the style.
|
||||
func (s Style) Italic() Style {
|
||||
return append(s, italicAttr)
|
||||
// Italic appends the italic or no italic style attribute to the style.
|
||||
// When v is true, text is rendered in italic. When false, italic is disabled.
|
||||
func (s Style) Italic(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrItalic)
|
||||
}
|
||||
return append(s, attrNoItalic)
|
||||
}
|
||||
|
||||
// Underline appends the underline style attribute to the style.
|
||||
func (s Style) Underline() Style {
|
||||
return append(s, underlineAttr)
|
||||
// Underline appends the underline or no underline style attribute to the style.
|
||||
// When v is true, text is underlined. When false, underline is disabled.
|
||||
func (s Style) Underline(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrUnderline)
|
||||
}
|
||||
return append(s, attrNoUnderline)
|
||||
}
|
||||
|
||||
// UnderlineStyle appends the underline style attribute to the style.
|
||||
func (s Style) UnderlineStyle(u UnderlineStyle) Style {
|
||||
// Supports various underline styles including single, double, curly, dotted,
|
||||
// and dashed.
|
||||
func (s Style) UnderlineStyle(u Underline) Style {
|
||||
switch u {
|
||||
case NoUnderlineStyle:
|
||||
return s.NoUnderline()
|
||||
case SingleUnderlineStyle:
|
||||
return s.Underline()
|
||||
case DoubleUnderlineStyle:
|
||||
return append(s, doubleUnderlineStyle)
|
||||
case CurlyUnderlineStyle:
|
||||
return append(s, curlyUnderlineStyle)
|
||||
case DottedUnderlineStyle:
|
||||
return append(s, dottedUnderlineStyle)
|
||||
case DashedUnderlineStyle:
|
||||
return append(s, dashedUnderlineStyle)
|
||||
case UnderlineNone:
|
||||
return s.Underline(false)
|
||||
case UnderlineSingle:
|
||||
return s.Underline(true)
|
||||
case UnderlineDouble:
|
||||
return append(s, underlineDouble)
|
||||
case UnderlineCurly:
|
||||
return append(s, underlineCurly)
|
||||
case UnderlineDotted:
|
||||
return append(s, underlineDotted)
|
||||
case UnderlineDashed:
|
||||
return append(s, underlineDashed)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// DoubleUnderline appends the double underline style attribute to the style.
|
||||
// This is a convenience method for UnderlineStyle(DoubleUnderlineStyle).
|
||||
func (s Style) DoubleUnderline() Style {
|
||||
return s.UnderlineStyle(DoubleUnderlineStyle)
|
||||
// Blink appends the slow blink or no blink style attribute to the style.
|
||||
// When v is true, text blinks slowly (less than 150 per minute). When false,
|
||||
// blinking is disabled.
|
||||
func (s Style) Blink(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrBlink)
|
||||
}
|
||||
return append(s, attrNoBlink)
|
||||
}
|
||||
|
||||
// CurlyUnderline appends the curly underline style attribute to the style.
|
||||
// This is a convenience method for UnderlineStyle(CurlyUnderlineStyle).
|
||||
func (s Style) CurlyUnderline() Style {
|
||||
return s.UnderlineStyle(CurlyUnderlineStyle)
|
||||
// RapidBlink appends the rapid blink or no blink style attribute to the style.
|
||||
// When v is true, text blinks rapidly (150+ per minute). When false, blinking
|
||||
// is disabled.
|
||||
//
|
||||
// Note that this is not widely supported in terminal emulators.
|
||||
func (s Style) RapidBlink(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrRapidBlink)
|
||||
}
|
||||
return append(s, attrNoBlink)
|
||||
}
|
||||
|
||||
// DottedUnderline appends the dotted underline style attribute to the style.
|
||||
// This is a convenience method for UnderlineStyle(DottedUnderlineStyle).
|
||||
func (s Style) DottedUnderline() Style {
|
||||
return s.UnderlineStyle(DottedUnderlineStyle)
|
||||
// Reverse appends the reverse or no reverse style attribute to the style.
|
||||
// When v is true, foreground and background colors are swapped. When false,
|
||||
// reverse video is disabled.
|
||||
func (s Style) Reverse(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrReverse)
|
||||
}
|
||||
return append(s, attrNoReverse)
|
||||
}
|
||||
|
||||
// DashedUnderline appends the dashed underline style attribute to the style.
|
||||
// This is a convenience method for UnderlineStyle(DashedUnderlineStyle).
|
||||
func (s Style) DashedUnderline() Style {
|
||||
return s.UnderlineStyle(DashedUnderlineStyle)
|
||||
// Conceal appends the conceal or no conceal style attribute to the style.
|
||||
// When v is true, text is hidden/concealed. When false, concealment is
|
||||
// disabled.
|
||||
func (s Style) Conceal(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrConceal)
|
||||
}
|
||||
return append(s, attrNoConceal)
|
||||
}
|
||||
|
||||
// SlowBlink appends the slow blink style attribute to the style.
|
||||
func (s Style) SlowBlink() Style {
|
||||
return append(s, slowBlinkAttr)
|
||||
// Strikethrough appends the strikethrough or no strikethrough style attribute
|
||||
// to the style. When v is true, text is rendered with a horizontal line through
|
||||
// it. When false, strikethrough is disabled.
|
||||
func (s Style) Strikethrough(v bool) Style {
|
||||
if v {
|
||||
return append(s, attrStrikethrough)
|
||||
}
|
||||
return append(s, attrNoStrikethrough)
|
||||
}
|
||||
|
||||
// RapidBlink appends the rapid blink style attribute to the style.
|
||||
func (s Style) RapidBlink() Style {
|
||||
return append(s, rapidBlinkAttr)
|
||||
}
|
||||
|
||||
// Reverse appends the reverse style attribute to the style.
|
||||
func (s Style) Reverse() Style {
|
||||
return append(s, reverseAttr)
|
||||
}
|
||||
|
||||
// Conceal appends the conceal style attribute to the style.
|
||||
func (s Style) Conceal() Style {
|
||||
return append(s, concealAttr)
|
||||
}
|
||||
|
||||
// Strikethrough appends the strikethrough style attribute to the style.
|
||||
func (s Style) Strikethrough() Style {
|
||||
return append(s, strikethroughAttr)
|
||||
}
|
||||
|
||||
// NormalIntensity appends the normal intensity style attribute to the style.
|
||||
func (s Style) NormalIntensity() Style {
|
||||
return append(s, normalIntensityAttr)
|
||||
// Normal appends the normal intensity style attribute to the style. This
|
||||
// resets [Style.Bold] and [Style.Faint] attributes.
|
||||
func (s Style) Normal() Style {
|
||||
return append(s, attrNormalIntensity)
|
||||
}
|
||||
|
||||
// NoItalic appends the no italic style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Italic](false) instead.
|
||||
func (s Style) NoItalic() Style {
|
||||
return append(s, noItalicAttr)
|
||||
return append(s, attrNoItalic)
|
||||
}
|
||||
|
||||
// NoUnderline appends the no underline style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Underline](false) instead.
|
||||
func (s Style) NoUnderline() Style {
|
||||
return append(s, noUnderlineAttr)
|
||||
return append(s, attrNoUnderline)
|
||||
}
|
||||
|
||||
// NoBlink appends the no blink style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Blink](false) or [Style.RapidBlink](false) instead.
|
||||
func (s Style) NoBlink() Style {
|
||||
return append(s, noBlinkAttr)
|
||||
return append(s, attrNoBlink)
|
||||
}
|
||||
|
||||
// NoReverse appends the no reverse style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Reverse](false) instead.
|
||||
func (s Style) NoReverse() Style {
|
||||
return append(s, noReverseAttr)
|
||||
return append(s, attrNoReverse)
|
||||
}
|
||||
|
||||
// NoConceal appends the no conceal style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Conceal](false) instead.
|
||||
func (s Style) NoConceal() Style {
|
||||
return append(s, noConcealAttr)
|
||||
return append(s, attrNoConceal)
|
||||
}
|
||||
|
||||
// NoStrikethrough appends the no strikethrough style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.Strikethrough](false) instead.
|
||||
func (s Style) NoStrikethrough() Style {
|
||||
return append(s, noStrikethroughAttr)
|
||||
return append(s, attrNoStrikethrough)
|
||||
}
|
||||
|
||||
// DefaultForegroundColor appends the default foreground color style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.ForegroundColor](nil) instead.
|
||||
func (s Style) DefaultForegroundColor() Style {
|
||||
return append(s, defaultForegroundColorAttr)
|
||||
return append(s, attrDefaultForegroundColor)
|
||||
}
|
||||
|
||||
// DefaultBackgroundColor appends the default background color style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.BackgroundColor](nil) instead.
|
||||
func (s Style) DefaultBackgroundColor() Style {
|
||||
return append(s, defaultBackgroundColorAttr)
|
||||
return append(s, attrDefaultBackgroundColor)
|
||||
}
|
||||
|
||||
// DefaultUnderlineColor appends the default underline color style attribute to the style.
|
||||
//
|
||||
// Deprecated: use [Style.UnderlineColor](nil) instead.
|
||||
func (s Style) DefaultUnderlineColor() Style {
|
||||
return append(s, defaultUnderlineColorAttr)
|
||||
return append(s, attrDefaultUnderlineColor)
|
||||
}
|
||||
|
||||
// ForegroundColor appends the foreground color style attribute to the style.
|
||||
// If c is nil, the default foreground color is used. Supports [BasicColor],
|
||||
// [IndexedColor] (256-color), and [color.Color] (24-bit RGB).
|
||||
func (s Style) ForegroundColor(c Color) Style {
|
||||
if c == nil {
|
||||
return append(s, attrDefaultForegroundColor)
|
||||
}
|
||||
return append(s, foregroundColorString(c))
|
||||
}
|
||||
|
||||
// BackgroundColor appends the background color style attribute to the style.
|
||||
// If c is nil, the default background color is used. Supports [BasicColor],
|
||||
// [IndexedColor] (256-color), and [color.Color] (24-bit RGB).
|
||||
func (s Style) BackgroundColor(c Color) Style {
|
||||
if c == nil {
|
||||
return append(s, attrDefaultBackgroundColor)
|
||||
}
|
||||
return append(s, backgroundColorString(c))
|
||||
}
|
||||
|
||||
// UnderlineColor appends the underline color style attribute to the style.
|
||||
// If c is nil, the default underline color is used. Supports [BasicColor],
|
||||
// [IndexedColor] (256-color), and [color.Color] (24-bit RGB).
|
||||
func (s Style) UnderlineColor(c Color) Style {
|
||||
if c == nil {
|
||||
return append(s, attrDefaultUnderlineColor)
|
||||
}
|
||||
return append(s, underlineColorString(c))
|
||||
}
|
||||
|
||||
// Underline represents an ANSI SGR (Select Graphic Rendition) underline style.
|
||||
type Underline = byte
|
||||
|
||||
// UnderlineStyle represents an ANSI SGR (Select Graphic Rendition) underline
|
||||
// style.
|
||||
//
|
||||
// Deprecated: use [Underline] instead.
|
||||
type UnderlineStyle = byte
|
||||
|
||||
const (
|
||||
doubleUnderlineStyle = "4:2"
|
||||
curlyUnderlineStyle = "4:3"
|
||||
dottedUnderlineStyle = "4:4"
|
||||
dashedUnderlineStyle = "4:5"
|
||||
underlineDouble = "4:2"
|
||||
underlineCurly = "4:3"
|
||||
underlineDotted = "4:4"
|
||||
underlineDashed = "4:5"
|
||||
)
|
||||
|
||||
// Underline styles constants.
|
||||
const (
|
||||
// NoUnderlineStyle is the default underline style.
|
||||
NoUnderlineStyle UnderlineStyle = iota
|
||||
// SingleUnderlineStyle is a single underline style.
|
||||
UnderlineNone Underline = iota
|
||||
UnderlineSingle
|
||||
UnderlineDouble
|
||||
UnderlineCurly
|
||||
UnderlineDotted
|
||||
UnderlineDashed
|
||||
)
|
||||
|
||||
// Underline styles constants.
|
||||
//
|
||||
// Deprecated: use [UnderlineNone], [UnderlineSingle], etc. instead.
|
||||
const (
|
||||
NoUnderlineStyle Underline = iota
|
||||
SingleUnderlineStyle
|
||||
// DoubleUnderlineStyle is a double underline style.
|
||||
DoubleUnderlineStyle
|
||||
// CurlyUnderlineStyle is a curly underline style.
|
||||
CurlyUnderlineStyle
|
||||
// DottedUnderlineStyle is a dotted underline style.
|
||||
DottedUnderlineStyle
|
||||
// DashedUnderlineStyle is a dashed underline style.
|
||||
DashedUnderlineStyle
|
||||
)
|
||||
|
||||
// Underline styles constants.
|
||||
//
|
||||
// Deprecated: use [UnderlineNone], [UnderlineSingle], etc. instead.
|
||||
const (
|
||||
UnderlineStyleNone Underline = iota
|
||||
UnderlineStyleSingle
|
||||
UnderlineStyleDouble
|
||||
UnderlineStyleCurly
|
||||
UnderlineStyleDotted
|
||||
UnderlineStyleDashed
|
||||
)
|
||||
|
||||
// SGR (Select Graphic Rendition) style attributes.
|
||||
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
||||
const (
|
||||
ResetAttr Attr = 0
|
||||
BoldAttr Attr = 1
|
||||
FaintAttr Attr = 2
|
||||
ItalicAttr Attr = 3
|
||||
UnderlineAttr Attr = 4
|
||||
SlowBlinkAttr Attr = 5
|
||||
RapidBlinkAttr Attr = 6
|
||||
ReverseAttr Attr = 7
|
||||
ConcealAttr Attr = 8
|
||||
StrikethroughAttr Attr = 9
|
||||
NormalIntensityAttr Attr = 22
|
||||
NoItalicAttr Attr = 23
|
||||
NoUnderlineAttr Attr = 24
|
||||
NoBlinkAttr Attr = 25
|
||||
NoReverseAttr Attr = 27
|
||||
NoConcealAttr Attr = 28
|
||||
NoStrikethroughAttr Attr = 29
|
||||
BlackForegroundColorAttr Attr = 30
|
||||
RedForegroundColorAttr Attr = 31
|
||||
GreenForegroundColorAttr Attr = 32
|
||||
YellowForegroundColorAttr Attr = 33
|
||||
BlueForegroundColorAttr Attr = 34
|
||||
MagentaForegroundColorAttr Attr = 35
|
||||
CyanForegroundColorAttr Attr = 36
|
||||
WhiteForegroundColorAttr Attr = 37
|
||||
ExtendedForegroundColorAttr Attr = 38
|
||||
DefaultForegroundColorAttr Attr = 39
|
||||
BlackBackgroundColorAttr Attr = 40
|
||||
RedBackgroundColorAttr Attr = 41
|
||||
GreenBackgroundColorAttr Attr = 42
|
||||
YellowBackgroundColorAttr Attr = 43
|
||||
BlueBackgroundColorAttr Attr = 44
|
||||
MagentaBackgroundColorAttr Attr = 45
|
||||
CyanBackgroundColorAttr Attr = 46
|
||||
WhiteBackgroundColorAttr Attr = 47
|
||||
ExtendedBackgroundColorAttr Attr = 48
|
||||
DefaultBackgroundColorAttr Attr = 49
|
||||
ExtendedUnderlineColorAttr Attr = 58
|
||||
DefaultUnderlineColorAttr Attr = 59
|
||||
BrightBlackForegroundColorAttr Attr = 90
|
||||
BrightRedForegroundColorAttr Attr = 91
|
||||
BrightGreenForegroundColorAttr Attr = 92
|
||||
BrightYellowForegroundColorAttr Attr = 93
|
||||
BrightBlueForegroundColorAttr Attr = 94
|
||||
BrightMagentaForegroundColorAttr Attr = 95
|
||||
BrightCyanForegroundColorAttr Attr = 96
|
||||
BrightWhiteForegroundColorAttr Attr = 97
|
||||
BrightBlackBackgroundColorAttr Attr = 100
|
||||
BrightRedBackgroundColorAttr Attr = 101
|
||||
BrightGreenBackgroundColorAttr Attr = 102
|
||||
BrightYellowBackgroundColorAttr Attr = 103
|
||||
BrightBlueBackgroundColorAttr Attr = 104
|
||||
BrightMagentaBackgroundColorAttr Attr = 105
|
||||
BrightCyanBackgroundColorAttr Attr = 106
|
||||
BrightWhiteBackgroundColorAttr Attr = 107
|
||||
AttrReset Attr = 0
|
||||
AttrBold Attr = 1
|
||||
AttrFaint Attr = 2
|
||||
AttrItalic Attr = 3
|
||||
AttrUnderline Attr = 4
|
||||
AttrBlink Attr = 5
|
||||
AttrRapidBlink Attr = 6
|
||||
AttrReverse Attr = 7
|
||||
AttrConceal Attr = 8
|
||||
AttrStrikethrough Attr = 9
|
||||
AttrNormalIntensity Attr = 22
|
||||
AttrNoItalic Attr = 23
|
||||
AttrNoUnderline Attr = 24
|
||||
AttrNoBlink Attr = 25
|
||||
AttrNoReverse Attr = 27
|
||||
AttrNoConceal Attr = 28
|
||||
AttrNoStrikethrough Attr = 29
|
||||
AttrBlackForegroundColor Attr = 30
|
||||
AttrRedForegroundColor Attr = 31
|
||||
AttrGreenForegroundColor Attr = 32
|
||||
AttrYellowForegroundColor Attr = 33
|
||||
AttrBlueForegroundColor Attr = 34
|
||||
AttrMagentaForegroundColor Attr = 35
|
||||
AttrCyanForegroundColor Attr = 36
|
||||
AttrWhiteForegroundColor Attr = 37
|
||||
AttrExtendedForegroundColor Attr = 38
|
||||
AttrDefaultForegroundColor Attr = 39
|
||||
AttrBlackBackgroundColor Attr = 40
|
||||
AttrRedBackgroundColor Attr = 41
|
||||
AttrGreenBackgroundColor Attr = 42
|
||||
AttrYellowBackgroundColor Attr = 43
|
||||
AttrBlueBackgroundColor Attr = 44
|
||||
AttrMagentaBackgroundColor Attr = 45
|
||||
AttrCyanBackgroundColor Attr = 46
|
||||
AttrWhiteBackgroundColor Attr = 47
|
||||
AttrExtendedBackgroundColor Attr = 48
|
||||
AttrDefaultBackgroundColor Attr = 49
|
||||
AttrExtendedUnderlineColor Attr = 58
|
||||
AttrDefaultUnderlineColor Attr = 59
|
||||
AttrBrightBlackForegroundColor Attr = 90
|
||||
AttrBrightRedForegroundColor Attr = 91
|
||||
AttrBrightGreenForegroundColor Attr = 92
|
||||
AttrBrightYellowForegroundColor Attr = 93
|
||||
AttrBrightBlueForegroundColor Attr = 94
|
||||
AttrBrightMagentaForegroundColor Attr = 95
|
||||
AttrBrightCyanForegroundColor Attr = 96
|
||||
AttrBrightWhiteForegroundColor Attr = 97
|
||||
AttrBrightBlackBackgroundColor Attr = 100
|
||||
AttrBrightRedBackgroundColor Attr = 101
|
||||
AttrBrightGreenBackgroundColor Attr = 102
|
||||
AttrBrightYellowBackgroundColor Attr = 103
|
||||
AttrBrightBlueBackgroundColor Attr = 104
|
||||
AttrBrightMagentaBackgroundColor Attr = 105
|
||||
AttrBrightCyanBackgroundColor Attr = 106
|
||||
AttrBrightWhiteBackgroundColor Attr = 107
|
||||
|
||||
RGBColorIntroducerAttr Attr = 2
|
||||
ExtendedColorIntroducerAttr Attr = 5
|
||||
AttrRGBColorIntroducer Attr = 2
|
||||
AttrExtendedColorIntroducer Attr = 5
|
||||
)
|
||||
|
||||
// SGR (Select Graphic Rendition) style attributes.
|
||||
//
|
||||
// Deprecated: use Attr* constants instead.
|
||||
const (
|
||||
ResetAttr = AttrReset
|
||||
BoldAttr = AttrBold
|
||||
FaintAttr = AttrFaint
|
||||
ItalicAttr = AttrItalic
|
||||
UnderlineAttr = AttrUnderline
|
||||
SlowBlinkAttr = AttrBlink
|
||||
RapidBlinkAttr = AttrRapidBlink
|
||||
ReverseAttr = AttrReverse
|
||||
ConcealAttr = AttrConceal
|
||||
StrikethroughAttr = AttrStrikethrough
|
||||
NormalIntensityAttr = AttrNormalIntensity
|
||||
NoItalicAttr = AttrNoItalic
|
||||
NoUnderlineAttr = AttrNoUnderline
|
||||
NoBlinkAttr = AttrNoBlink
|
||||
NoReverseAttr = AttrNoReverse
|
||||
NoConcealAttr = AttrNoConceal
|
||||
NoStrikethroughAttr = AttrNoStrikethrough
|
||||
BlackForegroundColorAttr = AttrBlackForegroundColor
|
||||
RedForegroundColorAttr = AttrRedForegroundColor
|
||||
GreenForegroundColorAttr = AttrGreenForegroundColor
|
||||
YellowForegroundColorAttr = AttrYellowForegroundColor
|
||||
BlueForegroundColorAttr = AttrBlueForegroundColor
|
||||
MagentaForegroundColorAttr = AttrMagentaForegroundColor
|
||||
CyanForegroundColorAttr = AttrCyanForegroundColor
|
||||
WhiteForegroundColorAttr = AttrWhiteForegroundColor
|
||||
ExtendedForegroundColorAttr = AttrExtendedForegroundColor
|
||||
DefaultForegroundColorAttr = AttrDefaultForegroundColor
|
||||
BlackBackgroundColorAttr = AttrBlackBackgroundColor
|
||||
RedBackgroundColorAttr = AttrRedBackgroundColor
|
||||
GreenBackgroundColorAttr = AttrGreenBackgroundColor
|
||||
YellowBackgroundColorAttr = AttrYellowBackgroundColor
|
||||
BlueBackgroundColorAttr = AttrBlueBackgroundColor
|
||||
MagentaBackgroundColorAttr = AttrMagentaBackgroundColor
|
||||
CyanBackgroundColorAttr = AttrCyanBackgroundColor
|
||||
WhiteBackgroundColorAttr = AttrWhiteBackgroundColor
|
||||
ExtendedBackgroundColorAttr = AttrExtendedBackgroundColor
|
||||
DefaultBackgroundColorAttr = AttrDefaultBackgroundColor
|
||||
ExtendedUnderlineColorAttr = AttrExtendedUnderlineColor
|
||||
DefaultUnderlineColorAttr = AttrDefaultUnderlineColor
|
||||
BrightBlackForegroundColorAttr = AttrBrightBlackForegroundColor
|
||||
BrightRedForegroundColorAttr = AttrBrightRedForegroundColor
|
||||
BrightGreenForegroundColorAttr = AttrBrightGreenForegroundColor
|
||||
BrightYellowForegroundColorAttr = AttrBrightYellowForegroundColor
|
||||
BrightBlueForegroundColorAttr = AttrBrightBlueForegroundColor
|
||||
BrightMagentaForegroundColorAttr = AttrBrightMagentaForegroundColor
|
||||
BrightCyanForegroundColorAttr = AttrBrightCyanForegroundColor
|
||||
BrightWhiteForegroundColorAttr = AttrBrightWhiteForegroundColor
|
||||
BrightBlackBackgroundColorAttr = AttrBrightBlackBackgroundColor
|
||||
BrightRedBackgroundColorAttr = AttrBrightRedBackgroundColor
|
||||
BrightGreenBackgroundColorAttr = AttrBrightGreenBackgroundColor
|
||||
BrightYellowBackgroundColorAttr = AttrBrightYellowBackgroundColor
|
||||
BrightBlueBackgroundColorAttr = AttrBrightBlueBackgroundColor
|
||||
BrightMagentaBackgroundColorAttr = AttrBrightMagentaBackgroundColor
|
||||
BrightCyanBackgroundColorAttr = AttrBrightCyanBackgroundColor
|
||||
BrightWhiteBackgroundColorAttr = AttrBrightWhiteBackgroundColor
|
||||
RGBColorIntroducerAttr = AttrRGBColorIntroducer
|
||||
ExtendedColorIntroducerAttr = AttrExtendedColorIntroducer
|
||||
)
|
||||
|
||||
const (
|
||||
resetAttr = "0"
|
||||
boldAttr = "1"
|
||||
faintAttr = "2"
|
||||
italicAttr = "3"
|
||||
underlineAttr = "4"
|
||||
slowBlinkAttr = "5"
|
||||
rapidBlinkAttr = "6"
|
||||
reverseAttr = "7"
|
||||
concealAttr = "8"
|
||||
strikethroughAttr = "9"
|
||||
normalIntensityAttr = "22"
|
||||
noItalicAttr = "23"
|
||||
noUnderlineAttr = "24"
|
||||
noBlinkAttr = "25"
|
||||
noReverseAttr = "27"
|
||||
noConcealAttr = "28"
|
||||
noStrikethroughAttr = "29"
|
||||
blackForegroundColorAttr = "30"
|
||||
redForegroundColorAttr = "31"
|
||||
greenForegroundColorAttr = "32"
|
||||
yellowForegroundColorAttr = "33"
|
||||
blueForegroundColorAttr = "34"
|
||||
magentaForegroundColorAttr = "35"
|
||||
cyanForegroundColorAttr = "36"
|
||||
whiteForegroundColorAttr = "37"
|
||||
extendedForegroundColorAttr = "38"
|
||||
defaultForegroundColorAttr = "39"
|
||||
blackBackgroundColorAttr = "40"
|
||||
redBackgroundColorAttr = "41"
|
||||
greenBackgroundColorAttr = "42"
|
||||
yellowBackgroundColorAttr = "43"
|
||||
blueBackgroundColorAttr = "44"
|
||||
magentaBackgroundColorAttr = "45"
|
||||
cyanBackgroundColorAttr = "46"
|
||||
whiteBackgroundColorAttr = "47"
|
||||
extendedBackgroundColorAttr = "48"
|
||||
defaultBackgroundColorAttr = "49"
|
||||
extendedUnderlineColorAttr = "58"
|
||||
defaultUnderlineColorAttr = "59"
|
||||
brightBlackForegroundColorAttr = "90"
|
||||
brightRedForegroundColorAttr = "91"
|
||||
brightGreenForegroundColorAttr = "92"
|
||||
brightYellowForegroundColorAttr = "93"
|
||||
brightBlueForegroundColorAttr = "94"
|
||||
brightMagentaForegroundColorAttr = "95"
|
||||
brightCyanForegroundColorAttr = "96"
|
||||
brightWhiteForegroundColorAttr = "97"
|
||||
brightBlackBackgroundColorAttr = "100"
|
||||
brightRedBackgroundColorAttr = "101"
|
||||
brightGreenBackgroundColorAttr = "102"
|
||||
brightYellowBackgroundColorAttr = "103"
|
||||
brightBlueBackgroundColorAttr = "104"
|
||||
brightMagentaBackgroundColorAttr = "105"
|
||||
brightCyanBackgroundColorAttr = "106"
|
||||
brightWhiteBackgroundColorAttr = "107"
|
||||
attrReset = "0"
|
||||
attrBold = "1"
|
||||
attrFaint = "2"
|
||||
attrItalic = "3"
|
||||
attrUnderline = "4"
|
||||
attrBlink = "5"
|
||||
attrRapidBlink = "6"
|
||||
attrReverse = "7"
|
||||
attrConceal = "8"
|
||||
attrStrikethrough = "9"
|
||||
attrNormalIntensity = "22"
|
||||
attrNoItalic = "23"
|
||||
attrNoUnderline = "24"
|
||||
attrNoBlink = "25"
|
||||
attrNoReverse = "27"
|
||||
attrNoConceal = "28"
|
||||
attrNoStrikethrough = "29"
|
||||
attrBlackForegroundColor = "30"
|
||||
attrRedForegroundColor = "31"
|
||||
attrGreenForegroundColor = "32"
|
||||
attrYellowForegroundColor = "33"
|
||||
attrBlueForegroundColor = "34"
|
||||
attrMagentaForegroundColor = "35"
|
||||
attrCyanForegroundColor = "36"
|
||||
attrWhiteForegroundColor = "37"
|
||||
attrExtendedForegroundColor = "38"
|
||||
attrDefaultForegroundColor = "39"
|
||||
attrBlackBackgroundColor = "40"
|
||||
attrRedBackgroundColor = "41"
|
||||
attrGreenBackgroundColor = "42"
|
||||
attrYellowBackgroundColor = "43"
|
||||
attrBlueBackgroundColor = "44"
|
||||
attrMagentaBackgroundColor = "45"
|
||||
attrCyanBackgroundColor = "46"
|
||||
attrWhiteBackgroundColor = "47"
|
||||
attrExtendedBackgroundColor = "48"
|
||||
attrDefaultBackgroundColor = "49"
|
||||
attrExtendedUnderlineColor = "58"
|
||||
attrDefaultUnderlineColor = "59"
|
||||
attrBrightBlackForegroundColor = "90"
|
||||
attrBrightRedForegroundColor = "91"
|
||||
attrBrightGreenForegroundColor = "92"
|
||||
attrBrightYellowForegroundColor = "93"
|
||||
attrBrightBlueForegroundColor = "94"
|
||||
attrBrightMagentaForegroundColor = "95"
|
||||
attrBrightCyanForegroundColor = "96"
|
||||
attrBrightWhiteForegroundColor = "97"
|
||||
attrBrightBlackBackgroundColor = "100"
|
||||
attrBrightRedBackgroundColor = "101"
|
||||
attrBrightGreenBackgroundColor = "102"
|
||||
attrBrightYellowBackgroundColor = "103"
|
||||
attrBrightBlueBackgroundColor = "104"
|
||||
attrBrightMagentaBackgroundColor = "105"
|
||||
attrBrightCyanBackgroundColor = "106"
|
||||
attrBrightWhiteBackgroundColor = "107"
|
||||
)
|
||||
|
||||
// foregroundColorString returns the style SGR attribute for the given
|
||||
@ -364,42 +504,44 @@ const (
|
||||
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
||||
func foregroundColorString(c Color) string {
|
||||
switch c := c.(type) {
|
||||
case nil:
|
||||
return attrDefaultForegroundColor
|
||||
case BasicColor:
|
||||
// 3-bit or 4-bit ANSI foreground
|
||||
// "3<n>" or "9<n>" where n is the color number from 0 to 7
|
||||
switch c {
|
||||
case Black:
|
||||
return blackForegroundColorAttr
|
||||
return attrBlackForegroundColor
|
||||
case Red:
|
||||
return redForegroundColorAttr
|
||||
return attrRedForegroundColor
|
||||
case Green:
|
||||
return greenForegroundColorAttr
|
||||
return attrGreenForegroundColor
|
||||
case Yellow:
|
||||
return yellowForegroundColorAttr
|
||||
return attrYellowForegroundColor
|
||||
case Blue:
|
||||
return blueForegroundColorAttr
|
||||
return attrBlueForegroundColor
|
||||
case Magenta:
|
||||
return magentaForegroundColorAttr
|
||||
return attrMagentaForegroundColor
|
||||
case Cyan:
|
||||
return cyanForegroundColorAttr
|
||||
return attrCyanForegroundColor
|
||||
case White:
|
||||
return whiteForegroundColorAttr
|
||||
return attrWhiteForegroundColor
|
||||
case BrightBlack:
|
||||
return brightBlackForegroundColorAttr
|
||||
return attrBrightBlackForegroundColor
|
||||
case BrightRed:
|
||||
return brightRedForegroundColorAttr
|
||||
return attrBrightRedForegroundColor
|
||||
case BrightGreen:
|
||||
return brightGreenForegroundColorAttr
|
||||
return attrBrightGreenForegroundColor
|
||||
case BrightYellow:
|
||||
return brightYellowForegroundColorAttr
|
||||
return attrBrightYellowForegroundColor
|
||||
case BrightBlue:
|
||||
return brightBlueForegroundColorAttr
|
||||
return attrBrightBlueForegroundColor
|
||||
case BrightMagenta:
|
||||
return brightMagentaForegroundColorAttr
|
||||
return attrBrightMagentaForegroundColor
|
||||
case BrightCyan:
|
||||
return brightCyanForegroundColorAttr
|
||||
return attrBrightCyanForegroundColor
|
||||
case BrightWhite:
|
||||
return brightWhiteForegroundColorAttr
|
||||
return attrBrightWhiteForegroundColor
|
||||
}
|
||||
case ExtendedColor:
|
||||
// 256-color ANSI foreground
|
||||
@ -414,7 +556,7 @@ func foregroundColorString(c Color) string {
|
||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||
strconv.FormatUint(uint64(shift(b)), 10)
|
||||
}
|
||||
return defaultForegroundColorAttr
|
||||
return attrDefaultForegroundColor
|
||||
}
|
||||
|
||||
// backgroundColorString returns the style SGR attribute for the given
|
||||
@ -422,42 +564,44 @@ func foregroundColorString(c Color) string {
|
||||
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
||||
func backgroundColorString(c Color) string {
|
||||
switch c := c.(type) {
|
||||
case nil:
|
||||
return attrDefaultBackgroundColor
|
||||
case BasicColor:
|
||||
// 3-bit or 4-bit ANSI foreground
|
||||
// "4<n>" or "10<n>" where n is the color number from 0 to 7
|
||||
switch c {
|
||||
case Black:
|
||||
return blackBackgroundColorAttr
|
||||
return attrBlackBackgroundColor
|
||||
case Red:
|
||||
return redBackgroundColorAttr
|
||||
return attrRedBackgroundColor
|
||||
case Green:
|
||||
return greenBackgroundColorAttr
|
||||
return attrGreenBackgroundColor
|
||||
case Yellow:
|
||||
return yellowBackgroundColorAttr
|
||||
return attrYellowBackgroundColor
|
||||
case Blue:
|
||||
return blueBackgroundColorAttr
|
||||
return attrBlueBackgroundColor
|
||||
case Magenta:
|
||||
return magentaBackgroundColorAttr
|
||||
return attrMagentaBackgroundColor
|
||||
case Cyan:
|
||||
return cyanBackgroundColorAttr
|
||||
return attrCyanBackgroundColor
|
||||
case White:
|
||||
return whiteBackgroundColorAttr
|
||||
return attrWhiteBackgroundColor
|
||||
case BrightBlack:
|
||||
return brightBlackBackgroundColorAttr
|
||||
return attrBrightBlackBackgroundColor
|
||||
case BrightRed:
|
||||
return brightRedBackgroundColorAttr
|
||||
return attrBrightRedBackgroundColor
|
||||
case BrightGreen:
|
||||
return brightGreenBackgroundColorAttr
|
||||
return attrBrightGreenBackgroundColor
|
||||
case BrightYellow:
|
||||
return brightYellowBackgroundColorAttr
|
||||
return attrBrightYellowBackgroundColor
|
||||
case BrightBlue:
|
||||
return brightBlueBackgroundColorAttr
|
||||
return attrBrightBlueBackgroundColor
|
||||
case BrightMagenta:
|
||||
return brightMagentaBackgroundColorAttr
|
||||
return attrBrightMagentaBackgroundColor
|
||||
case BrightCyan:
|
||||
return brightCyanBackgroundColorAttr
|
||||
return attrBrightCyanBackgroundColor
|
||||
case BrightWhite:
|
||||
return brightWhiteBackgroundColorAttr
|
||||
return attrBrightWhiteBackgroundColor
|
||||
}
|
||||
case ExtendedColor:
|
||||
// 256-color ANSI foreground
|
||||
@ -472,7 +616,7 @@ func backgroundColorString(c Color) string {
|
||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||
strconv.FormatUint(uint64(shift(b)), 10)
|
||||
}
|
||||
return defaultBackgroundColorAttr
|
||||
return attrDefaultBackgroundColor
|
||||
}
|
||||
|
||||
// underlineColorString returns the style SGR attribute for the given underline
|
||||
@ -480,6 +624,8 @@ func backgroundColorString(c Color) string {
|
||||
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
||||
func underlineColorString(c Color) string {
|
||||
switch c := c.(type) {
|
||||
case nil:
|
||||
return attrDefaultUnderlineColor
|
||||
// NOTE: we can't use 3-bit and 4-bit ANSI color codes with underline
|
||||
// color, use 256-color instead.
|
||||
//
|
||||
@ -498,7 +644,7 @@ func underlineColorString(c Color) string {
|
||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||
strconv.FormatUint(uint64(shift(b)), 10)
|
||||
}
|
||||
return defaultUnderlineColorAttr
|
||||
return attrDefaultUnderlineColor
|
||||
}
|
||||
|
||||
// ReadStyleColor decodes a color from a slice of parameters. It returns the
|
||||
@ -526,7 +672,7 @@ func underlineColorString(c Color) string {
|
||||
// 2. Support ignoring and omitting the color space id (second parameter) with respect to RGB colors
|
||||
// 3. Support ignoring and omitting the 6th parameter with respect to RGB and CMY colors
|
||||
// 4. Support reading RGBA colors
|
||||
func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
func ReadStyleColor(params Params, co *color.Color) int {
|
||||
if len(params) < 2 { // Need at least SGR type and color type
|
||||
return 0
|
||||
}
|
||||
@ -535,7 +681,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
s := params[0]
|
||||
p := params[1]
|
||||
colorType := p.Param(0)
|
||||
n = 2
|
||||
n := 2
|
||||
|
||||
paramsfn := func() (p1, p2, p3, p4 int) {
|
||||
// Where should we start reading the color?
|
||||
@ -594,7 +740,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
B: uint8(b), //nolint:gosec
|
||||
A: 0xff,
|
||||
}
|
||||
return //nolint:nakedret
|
||||
return n
|
||||
|
||||
case 3: // CMY direct color
|
||||
if len(params) < 5 {
|
||||
@ -612,7 +758,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
Y: uint8(y), //nolint:gosec
|
||||
K: 0,
|
||||
}
|
||||
return //nolint:nakedret
|
||||
return n
|
||||
|
||||
case 4: // CMYK direct color
|
||||
if len(params) < 6 {
|
||||
@ -630,7 +776,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
Y: uint8(y), //nolint:gosec
|
||||
K: uint8(k), //nolint:gosec
|
||||
}
|
||||
return //nolint:nakedret
|
||||
return n
|
||||
|
||||
case 5: // indexed color
|
||||
if len(params) < 3 {
|
||||
@ -665,7 +811,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
B: uint8(b), //nolint:gosec
|
||||
A: uint8(a), //nolint:gosec
|
||||
}
|
||||
return //nolint:nakedret
|
||||
return n
|
||||
|
||||
default:
|
||||
return 0
|
||||
|
||||
57
vendor/github.com/charmbracelet/x/ansi/truncate.go
generated
vendored
57
vendor/github.com/charmbracelet/x/ansi/truncate.go
generated
vendored
@ -1,11 +1,11 @@
|
||||
package ansi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/x/ansi/parser"
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/rivo/uniseg"
|
||||
"github.com/clipperhouse/displaywidth"
|
||||
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||
)
|
||||
|
||||
// Cut the string, without adding any prefix or tail strings. This function is
|
||||
@ -74,12 +74,11 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
var cluster []byte
|
||||
var buf bytes.Buffer
|
||||
var cluster string
|
||||
var buf strings.Builder
|
||||
curWidth := 0
|
||||
ignoring := false
|
||||
pstate := parser.GroundState // initial state
|
||||
b := []byte(s)
|
||||
i := 0
|
||||
|
||||
// Here we iterate over the bytes of the string and collect printable
|
||||
@ -88,16 +87,12 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
//
|
||||
// Once we reach the given length, we start ignoring characters and only
|
||||
// collect ANSI escape codes until we reach the end of string.
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
for i < len(s) {
|
||||
state, action := parser.Table.Transition(pstate, s[i])
|
||||
if state == parser.Utf8State {
|
||||
// This action happens when we transition to the Utf8State.
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(cluster))
|
||||
}
|
||||
|
||||
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||
// increment the index by the length of the cluster
|
||||
i += len(cluster)
|
||||
curWidth += width
|
||||
@ -118,7 +113,7 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
continue
|
||||
}
|
||||
|
||||
buf.Write(cluster)
|
||||
buf.WriteString(cluster)
|
||||
|
||||
// Done collecting, now we're back in the ground state.
|
||||
pstate = parser.GroundState
|
||||
@ -152,7 +147,7 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
buf.WriteByte(b[i])
|
||||
buf.WriteByte(s[i])
|
||||
i++
|
||||
}
|
||||
|
||||
@ -193,27 +188,23 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
var cluster []byte
|
||||
var buf bytes.Buffer
|
||||
var cluster string
|
||||
var buf strings.Builder
|
||||
curWidth := 0
|
||||
ignoring := true
|
||||
pstate := parser.GroundState
|
||||
b := []byte(s)
|
||||
i := 0
|
||||
|
||||
for i < len(b) {
|
||||
for i < len(s) {
|
||||
if !ignoring {
|
||||
buf.Write(b[i:])
|
||||
buf.WriteString(s[i:])
|
||||
break
|
||||
}
|
||||
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
state, action := parser.Table.Transition(pstate, s[i])
|
||||
if state == parser.Utf8State {
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(cluster))
|
||||
}
|
||||
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||
|
||||
i += len(cluster)
|
||||
curWidth += width
|
||||
@ -224,7 +215,7 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
}
|
||||
|
||||
if curWidth > n {
|
||||
buf.Write(cluster)
|
||||
buf.WriteString(cluster)
|
||||
}
|
||||
|
||||
if ignoring {
|
||||
@ -259,7 +250,7 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
buf.WriteByte(b[i])
|
||||
buf.WriteByte(s[i])
|
||||
i++
|
||||
}
|
||||
|
||||
@ -278,22 +269,22 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
// You can use this with [Truncate], [TruncateLeft], and [Cut].
|
||||
func ByteToGraphemeRange(str string, byteStart, byteStop int) (charStart, charStop int) {
|
||||
bytePos, charPos := 0, 0
|
||||
gr := uniseg.NewGraphemes(str)
|
||||
gr := graphemes.FromString(str)
|
||||
for byteStart > bytePos {
|
||||
if !gr.Next() {
|
||||
break
|
||||
}
|
||||
bytePos += len(gr.Str())
|
||||
charPos += max(1, gr.Width())
|
||||
bytePos += len(gr.Value())
|
||||
charPos += max(1, displaywidth.String(gr.Value()))
|
||||
}
|
||||
charStart = charPos
|
||||
for byteStop > bytePos {
|
||||
if !gr.Next() {
|
||||
break
|
||||
}
|
||||
bytePos += len(gr.Str())
|
||||
charPos += max(1, gr.Width())
|
||||
bytePos += len(gr.Value())
|
||||
charPos += max(1, displaywidth.String(gr.Value()))
|
||||
}
|
||||
charStop = charPos
|
||||
return
|
||||
return charStart, charStop
|
||||
}
|
||||
|
||||
17
vendor/github.com/charmbracelet/x/ansi/urxvt.go
generated
vendored
Normal file
17
vendor/github.com/charmbracelet/x/ansi/urxvt.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package ansi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URxvtExt returns an escape sequence for calling a URxvt perl extension with
|
||||
// the given name and parameters.
|
||||
//
|
||||
// OSC 777 ; extension_name ; param1 ; param2 ; ... ST
|
||||
// OSC 777 ; extension_name ; param1 ; param2 ; ... BEL
|
||||
//
|
||||
// See: https://man.archlinux.org/man/extra/rxvt-unicode/urxvt.7.en#XTerm_Operating_System_Commands
|
||||
func URxvtExt(extension string, params ...string) string {
|
||||
return fmt.Sprintf("\x1b]777;%s;%s\x07", extension, strings.Join(params, ";"))
|
||||
}
|
||||
14
vendor/github.com/charmbracelet/x/ansi/width.go
generated
vendored
14
vendor/github.com/charmbracelet/x/ansi/width.go
generated
vendored
@ -4,8 +4,6 @@ import (
|
||||
"bytes"
|
||||
|
||||
"github.com/charmbracelet/x/ansi/parser"
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
// Strip removes ANSI escape codes from a string.
|
||||
@ -83,20 +81,16 @@ func stringWidth(m Method, s string) int {
|
||||
}
|
||||
|
||||
var (
|
||||
pstate = parser.GroundState // initial state
|
||||
cluster string
|
||||
width int
|
||||
pstate = parser.GroundState // initial state
|
||||
width int
|
||||
)
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
state, action := parser.Table.Transition(pstate, s[i])
|
||||
if state == parser.Utf8State {
|
||||
var w int
|
||||
cluster, _, w, _ = uniseg.FirstGraphemeClusterInString(s[i:], -1)
|
||||
if m == WcWidth {
|
||||
w = runewidth.StringWidth(cluster)
|
||||
}
|
||||
cluster, w := FirstGraphemeCluster(s[i:], m)
|
||||
width += w
|
||||
|
||||
i += len(cluster) - 1
|
||||
pstate = parser.GroundState
|
||||
continue
|
||||
|
||||
50
vendor/github.com/charmbracelet/x/ansi/wrap.go
generated
vendored
50
vendor/github.com/charmbracelet/x/ansi/wrap.go
generated
vendored
@ -2,12 +2,11 @@ package ansi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/charmbracelet/x/ansi/parser"
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
// nbsp is a non-breaking space.
|
||||
@ -55,12 +54,9 @@ func hardwrap(m Method, s string, limit int, preserveSpace bool) string {
|
||||
i := 0
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
if state == parser.Utf8State {
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(cluster))
|
||||
}
|
||||
cluster, width = FirstGraphemeCluster(b[i:], m)
|
||||
i += len(cluster)
|
||||
|
||||
if curWidth+width > limit {
|
||||
@ -192,10 +188,7 @@ func wordwrap(m Method, s string, limit int, breakpoints string) string {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(cluster))
|
||||
}
|
||||
cluster, width = FirstGraphemeCluster(b[i:], m)
|
||||
i += len(cluster)
|
||||
|
||||
r, _ := utf8.DecodeRune(cluster)
|
||||
@ -303,7 +296,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
cluster []byte
|
||||
cluster string
|
||||
buf bytes.Buffer
|
||||
word bytes.Buffer
|
||||
space bytes.Buffer
|
||||
@ -311,10 +304,12 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
curWidth int // written width of the line
|
||||
wordLen int // word buffer len without ANSI escape codes
|
||||
pstate = parser.GroundState // initial state
|
||||
b = []byte(s)
|
||||
)
|
||||
|
||||
addSpace := func() {
|
||||
if spaceWidth == 0 && space.Len() == 0 {
|
||||
return
|
||||
}
|
||||
curWidth += spaceWidth
|
||||
buf.Write(space.Bytes())
|
||||
space.Reset()
|
||||
@ -341,30 +336,27 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
i := 0
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
for i < len(s) {
|
||||
state, action := parser.Table.Transition(pstate, s[i])
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
width = runewidth.StringWidth(string(cluster))
|
||||
}
|
||||
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||
i += len(cluster)
|
||||
|
||||
r, _ := utf8.DecodeRune(cluster)
|
||||
r, _ := utf8.DecodeRuneInString(cluster)
|
||||
switch {
|
||||
case r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp: // nbsp is a non-breaking space
|
||||
addWord()
|
||||
space.WriteRune(r)
|
||||
spaceWidth += width
|
||||
case bytes.ContainsAny(cluster, breakpoints):
|
||||
case strings.ContainsAny(cluster, breakpoints):
|
||||
addSpace()
|
||||
if curWidth+wordLen+width > limit {
|
||||
word.Write(cluster)
|
||||
word.WriteString(cluster)
|
||||
wordLen += width
|
||||
} else {
|
||||
addWord()
|
||||
buf.Write(cluster)
|
||||
buf.WriteString(cluster)
|
||||
curWidth += width
|
||||
}
|
||||
default:
|
||||
@ -373,12 +365,17 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
addWord()
|
||||
}
|
||||
|
||||
word.Write(cluster)
|
||||
word.WriteString(cluster)
|
||||
wordLen += width
|
||||
|
||||
if curWidth+wordLen+spaceWidth > limit {
|
||||
addNewline()
|
||||
}
|
||||
|
||||
if wordLen == limit {
|
||||
// Hardwrap the word if it's too long
|
||||
addWord()
|
||||
}
|
||||
}
|
||||
|
||||
pstate = parser.GroundState
|
||||
@ -387,7 +384,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
|
||||
switch action {
|
||||
case parser.PrintAction, parser.ExecuteAction:
|
||||
switch r := rune(b[i]); {
|
||||
switch r := rune(s[i]); {
|
||||
case r == '\n':
|
||||
if wordLen == 0 {
|
||||
if curWidth+spaceWidth > limit {
|
||||
@ -424,6 +421,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
if curWidth == limit {
|
||||
addNewline()
|
||||
}
|
||||
|
||||
word.WriteRune(r)
|
||||
wordLen++
|
||||
|
||||
@ -438,7 +436,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
default:
|
||||
word.WriteByte(b[i])
|
||||
word.WriteByte(s[i])
|
||||
}
|
||||
|
||||
// We manage the UTF8 state separately manually above.
|
||||
|
||||
15
vendor/github.com/charmbracelet/x/cellbuf/buffer.go
generated
vendored
15
vendor/github.com/charmbracelet/x/cellbuf/buffer.go
generated
vendored
@ -1,3 +1,4 @@
|
||||
// Package cellbuf provides terminal cell buffer functionality.
|
||||
package cellbuf
|
||||
|
||||
import (
|
||||
@ -24,7 +25,7 @@ func NewCell(r rune, comb ...rune) (c *Cell) {
|
||||
}
|
||||
c.Comb = comb
|
||||
c.Width = runewidth.StringWidth(string(append([]rune{r}, comb...)))
|
||||
return
|
||||
return c
|
||||
}
|
||||
|
||||
// NewCellString returns a new cell with the given string content. This is a
|
||||
@ -46,7 +47,7 @@ func NewCellString(s string) (c *Cell) {
|
||||
c.Comb = append(c.Comb, r)
|
||||
}
|
||||
}
|
||||
return
|
||||
return c
|
||||
}
|
||||
|
||||
// NewGraphemeCell returns a new cell. This is a convenience function that
|
||||
@ -71,7 +72,7 @@ func newGraphemeCell(s string, w int) (c *Cell) {
|
||||
c.Comb = append(c.Comb, r)
|
||||
}
|
||||
}
|
||||
return
|
||||
return c
|
||||
}
|
||||
|
||||
// Line represents a line in the terminal.
|
||||
@ -104,7 +105,7 @@ func (l Line) String() (s string) {
|
||||
}
|
||||
}
|
||||
s = strings.TrimRight(s, " ")
|
||||
return
|
||||
return s
|
||||
}
|
||||
|
||||
// At returns the cell at the given x position.
|
||||
@ -150,7 +151,7 @@ func (l Line) set(x int, c *Cell, clone bool) bool {
|
||||
for j := 1; j < maxCellWidth && x-j >= 0; j++ {
|
||||
wide := l.At(x - j)
|
||||
if wide != nil && wide.Width > 1 && j < wide.Width {
|
||||
for k := 0; k < wide.Width; k++ {
|
||||
for k := range wide.Width {
|
||||
l[x-j+k] = wide.Clone().Blank()
|
||||
}
|
||||
break
|
||||
@ -206,7 +207,7 @@ func (b *Buffer) String() (s string) {
|
||||
s += "\r\n"
|
||||
}
|
||||
}
|
||||
return
|
||||
return s
|
||||
}
|
||||
|
||||
// Line returns a pointer to the line at the given y position.
|
||||
@ -296,7 +297,7 @@ func (b *Buffer) FillRect(c *Cell, rect Rectangle) {
|
||||
}
|
||||
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||
for x := rect.Min.X; x < rect.Max.X; x += cellWidth {
|
||||
b.setCell(x, y, c, false) //nolint:errcheck
|
||||
b.setCell(x, y, c, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
83
vendor/github.com/charmbracelet/x/cellbuf/cell.go
generated
vendored
83
vendor/github.com/charmbracelet/x/cellbuf/cell.go
generated
vendored
@ -96,7 +96,7 @@ func (c *Cell) Clear() bool {
|
||||
func (c *Cell) Clone() (n *Cell) {
|
||||
n = new(Cell)
|
||||
*n = *c
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
// Blank makes the cell a blank cell by setting the rune to a space, comb to
|
||||
@ -164,12 +164,12 @@ type UnderlineStyle = ansi.UnderlineStyle
|
||||
|
||||
// These are the available underline styles.
|
||||
const (
|
||||
NoUnderline = ansi.NoUnderlineStyle
|
||||
SingleUnderline = ansi.SingleUnderlineStyle
|
||||
DoubleUnderline = ansi.DoubleUnderlineStyle
|
||||
CurlyUnderline = ansi.CurlyUnderlineStyle
|
||||
DottedUnderline = ansi.DottedUnderlineStyle
|
||||
DashedUnderline = ansi.DashedUnderlineStyle
|
||||
NoUnderline = ansi.UnderlineStyleNone
|
||||
SingleUnderline = ansi.UnderlineStyleSingle
|
||||
DoubleUnderline = ansi.UnderlineStyleDouble
|
||||
CurlyUnderline = ansi.UnderlineStyleCurly
|
||||
DottedUnderline = ansi.UnderlineStyleDotted
|
||||
DashedUnderline = ansi.UnderlineStyleDashed
|
||||
)
|
||||
|
||||
// Style represents the Style of a cell.
|
||||
@ -189,7 +189,7 @@ func (s Style) Sequence() string {
|
||||
|
||||
var b ansi.Style
|
||||
|
||||
if s.Attrs != 0 {
|
||||
if s.Attrs != 0 { //nolint:nestif
|
||||
if s.Attrs&BoldAttr != 0 {
|
||||
b = b.Bold()
|
||||
}
|
||||
@ -197,36 +197,31 @@ func (s Style) Sequence() string {
|
||||
b = b.Faint()
|
||||
}
|
||||
if s.Attrs&ItalicAttr != 0 {
|
||||
b = b.Italic()
|
||||
b = b.Italic(true)
|
||||
}
|
||||
if s.Attrs&SlowBlinkAttr != 0 {
|
||||
b = b.SlowBlink()
|
||||
b = b.Blink(true)
|
||||
}
|
||||
if s.Attrs&RapidBlinkAttr != 0 {
|
||||
b = b.RapidBlink()
|
||||
b = b.RapidBlink(true)
|
||||
}
|
||||
if s.Attrs&ReverseAttr != 0 {
|
||||
b = b.Reverse()
|
||||
b = b.Reverse(true)
|
||||
}
|
||||
if s.Attrs&ConcealAttr != 0 {
|
||||
b = b.Conceal()
|
||||
b = b.Conceal(true)
|
||||
}
|
||||
if s.Attrs&StrikethroughAttr != 0 {
|
||||
b = b.Strikethrough()
|
||||
b = b.Strikethrough(true)
|
||||
}
|
||||
}
|
||||
if s.UlStyle != NoUnderline {
|
||||
switch s.UlStyle {
|
||||
case SingleUnderline:
|
||||
b = b.Underline()
|
||||
case DoubleUnderline:
|
||||
b = b.DoubleUnderline()
|
||||
case CurlyUnderline:
|
||||
b = b.CurlyUnderline()
|
||||
case DottedUnderline:
|
||||
b = b.DottedUnderline()
|
||||
case DashedUnderline:
|
||||
b = b.DashedUnderline()
|
||||
switch u := s.UlStyle; u {
|
||||
case NoUnderline:
|
||||
b = b.Underline(false)
|
||||
default:
|
||||
b = b.Underline(true)
|
||||
b = b.UnderlineStyle(u)
|
||||
}
|
||||
}
|
||||
if s.Fg != nil {
|
||||
@ -268,64 +263,48 @@ func (s Style) DiffSequence(o Style) string {
|
||||
isNormal bool
|
||||
)
|
||||
|
||||
if s.Attrs != o.Attrs {
|
||||
if s.Attrs != o.Attrs { //nolint:nestif
|
||||
if s.Attrs&BoldAttr != o.Attrs&BoldAttr {
|
||||
if s.Attrs&BoldAttr != 0 {
|
||||
b = b.Bold()
|
||||
} else if !isNormal {
|
||||
isNormal = true
|
||||
b = b.NormalIntensity()
|
||||
b = b.Normal()
|
||||
}
|
||||
}
|
||||
if s.Attrs&FaintAttr != o.Attrs&FaintAttr {
|
||||
if s.Attrs&FaintAttr != 0 {
|
||||
b = b.Faint()
|
||||
} else if !isNormal {
|
||||
b = b.NormalIntensity()
|
||||
b = b.Normal()
|
||||
}
|
||||
}
|
||||
if s.Attrs&ItalicAttr != o.Attrs&ItalicAttr {
|
||||
if s.Attrs&ItalicAttr != 0 {
|
||||
b = b.Italic()
|
||||
} else {
|
||||
b = b.NoItalic()
|
||||
}
|
||||
b = b.Italic(s.Attrs&ItalicAttr != 0)
|
||||
}
|
||||
if s.Attrs&SlowBlinkAttr != o.Attrs&SlowBlinkAttr {
|
||||
if s.Attrs&SlowBlinkAttr != 0 {
|
||||
b = b.SlowBlink()
|
||||
b = b.Blink(true)
|
||||
} else if !noBlink {
|
||||
noBlink = true
|
||||
b = b.NoBlink()
|
||||
b = b.Blink(false)
|
||||
}
|
||||
}
|
||||
if s.Attrs&RapidBlinkAttr != o.Attrs&RapidBlinkAttr {
|
||||
if s.Attrs&RapidBlinkAttr != 0 {
|
||||
b = b.RapidBlink()
|
||||
b = b.RapidBlink(true)
|
||||
} else if !noBlink {
|
||||
b = b.NoBlink()
|
||||
b = b.Blink(false)
|
||||
}
|
||||
}
|
||||
if s.Attrs&ReverseAttr != o.Attrs&ReverseAttr {
|
||||
if s.Attrs&ReverseAttr != 0 {
|
||||
b = b.Reverse()
|
||||
} else {
|
||||
b = b.NoReverse()
|
||||
}
|
||||
b = b.Reverse(s.Attrs&ReverseAttr != 0)
|
||||
}
|
||||
if s.Attrs&ConcealAttr != o.Attrs&ConcealAttr {
|
||||
if s.Attrs&ConcealAttr != 0 {
|
||||
b = b.Conceal()
|
||||
} else {
|
||||
b = b.NoConceal()
|
||||
}
|
||||
b = b.Conceal(s.Attrs&ConcealAttr != 0)
|
||||
}
|
||||
if s.Attrs&StrikethroughAttr != o.Attrs&StrikethroughAttr {
|
||||
if s.Attrs&StrikethroughAttr != 0 {
|
||||
b = b.Strikethrough()
|
||||
} else {
|
||||
b = b.NoStrikethrough()
|
||||
}
|
||||
b = b.Strikethrough(s.Attrs&StrikethroughAttr != 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/cellbuf/geom.go
generated
vendored
2
vendor/github.com/charmbracelet/x/cellbuf/geom.go
generated
vendored
@ -12,7 +12,7 @@ func Pos(x, y int) Position {
|
||||
return image.Pt(x, y)
|
||||
}
|
||||
|
||||
// Rectange represents a rectangle.
|
||||
// Rectangle represents a rectangle.
|
||||
type Rectangle = image.Rectangle
|
||||
|
||||
// Rect is a shorthand for Rectangle.
|
||||
|
||||
19
vendor/github.com/charmbracelet/x/cellbuf/hardscroll.go
generated
vendored
19
vendor/github.com/charmbracelet/x/cellbuf/hardscroll.go
generated
vendored
@ -75,7 +75,7 @@ func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam
|
||||
)
|
||||
|
||||
blank := s.clearBlank()
|
||||
if n > 0 {
|
||||
if n > 0 { //nolint:nestif
|
||||
// Scroll up (forward)
|
||||
v = s.scrollUp(n, top, bot, 0, maxY, blank)
|
||||
if !v {
|
||||
@ -99,7 +99,7 @@ func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam
|
||||
s.move(0, bot-n+1)
|
||||
s.clearToBottom(nil)
|
||||
} else {
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
s.move(0, bot-i)
|
||||
s.clearToEnd(nil, false)
|
||||
}
|
||||
@ -124,7 +124,7 @@ func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam
|
||||
// Clear newly shifted-in lines.
|
||||
if v &&
|
||||
(nonDestScrollRegion || (memoryBelow && top == 0)) {
|
||||
for i := 0; i < -n; i++ {
|
||||
for i := range -n {
|
||||
s.move(0, top+i)
|
||||
s.clearToEnd(nil, false)
|
||||
}
|
||||
@ -133,7 +133,7 @@ func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam
|
||||
}
|
||||
|
||||
if !v {
|
||||
return
|
||||
return v
|
||||
}
|
||||
|
||||
s.scrollBuffer(s.curbuf, n, top, bot, blank)
|
||||
@ -193,7 +193,7 @@ func (s *Screen) touchLine(width, height, y, n int, changed bool) {
|
||||
|
||||
// scrollUp scrolls the screen up by n lines.
|
||||
func (s *Screen) scrollUp(n, top, bot, minY, maxY int, blank *Cell) bool {
|
||||
if n == 1 && top == minY && bot == maxY {
|
||||
if n == 1 && top == minY && bot == maxY { //nolint:nestif
|
||||
s.move(0, bot)
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteByte('\n')
|
||||
@ -202,13 +202,14 @@ func (s *Screen) scrollUp(n, top, bot, minY, maxY int, blank *Cell) bool {
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.DeleteLine(1))
|
||||
} else if top == minY && bot == maxY {
|
||||
if s.xtermLike {
|
||||
supportsSU := s.caps.Contains(capSU)
|
||||
if supportsSU {
|
||||
s.move(0, bot)
|
||||
} else {
|
||||
s.move(0, top)
|
||||
}
|
||||
s.updatePen(blank)
|
||||
if s.xtermLike {
|
||||
if supportsSU {
|
||||
s.buf.WriteString(ansi.ScrollUp(n))
|
||||
} else {
|
||||
s.buf.WriteString(strings.Repeat("\n", n))
|
||||
@ -225,7 +226,7 @@ func (s *Screen) scrollUp(n, top, bot, minY, maxY int, blank *Cell) bool {
|
||||
|
||||
// scrollDown scrolls the screen down by n lines.
|
||||
func (s *Screen) scrollDown(n, top, bot, minY, maxY int, blank *Cell) bool {
|
||||
if n == 1 && top == minY && bot == maxY {
|
||||
if n == 1 && top == minY && bot == maxY { //nolint:nestif
|
||||
s.move(0, top)
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.ReverseIndex)
|
||||
@ -236,7 +237,7 @@ func (s *Screen) scrollDown(n, top, bot, minY, maxY int, blank *Cell) bool {
|
||||
} else if top == minY && bot == maxY {
|
||||
s.move(0, top)
|
||||
s.updatePen(blank)
|
||||
if s.xtermLike {
|
||||
if s.caps.Contains(capSD) {
|
||||
s.buf.WriteString(ansi.ScrollDown(n))
|
||||
} else {
|
||||
s.buf.WriteString(strings.Repeat(ansi.ReverseIndex, n))
|
||||
|
||||
16
vendor/github.com/charmbracelet/x/cellbuf/hashmap.go
generated
vendored
16
vendor/github.com/charmbracelet/x/cellbuf/hashmap.go
generated
vendored
@ -15,7 +15,7 @@ func hash(l Line) (h uint64) {
|
||||
}
|
||||
h += (h << 5) + uint64(r)
|
||||
}
|
||||
return
|
||||
return h
|
||||
}
|
||||
|
||||
// hashmap represents a single [Line] hash.
|
||||
@ -33,7 +33,7 @@ func (s *Screen) updateHashmap() {
|
||||
height := s.newbuf.Height()
|
||||
if len(s.oldhash) >= height && len(s.newhash) >= height {
|
||||
// rehash changed lines
|
||||
for i := 0; i < height; i++ {
|
||||
for i := range height {
|
||||
_, ok := s.touch[i]
|
||||
if ok {
|
||||
s.oldhash[i] = hash(s.curbuf.Line(i))
|
||||
@ -48,14 +48,14 @@ func (s *Screen) updateHashmap() {
|
||||
if len(s.newhash) != height {
|
||||
s.newhash = make([]uint64, height)
|
||||
}
|
||||
for i := 0; i < height; i++ {
|
||||
for i := range height {
|
||||
s.oldhash[i] = hash(s.curbuf.Line(i))
|
||||
s.newhash[i] = hash(s.newbuf.Line(i))
|
||||
}
|
||||
}
|
||||
|
||||
s.hashtab = make([]hashmap, height*2)
|
||||
for i := 0; i < height; i++ {
|
||||
for i := range height {
|
||||
hashval := s.oldhash[i]
|
||||
|
||||
// Find matching hash or empty slot
|
||||
@ -71,7 +71,7 @@ func (s *Screen) updateHashmap() {
|
||||
s.hashtab[idx].oldcount++
|
||||
s.hashtab[idx].oldindex = i
|
||||
}
|
||||
for i := 0; i < height; i++ {
|
||||
for i := range height {
|
||||
hashval := s.newhash[i]
|
||||
|
||||
// Find matching hash or empty slot
|
||||
@ -130,7 +130,7 @@ func (s *Screen) updateHashmap() {
|
||||
s.growHunks()
|
||||
}
|
||||
|
||||
// scrollOldhash
|
||||
// scrollOldhash.
|
||||
func (s *Screen) scrollOldhash(n, top, bot int) {
|
||||
if len(s.oldhash) == 0 {
|
||||
return
|
||||
@ -287,7 +287,7 @@ func (s *Screen) updateCost(from, to Line) (cost int) {
|
||||
cost++
|
||||
}
|
||||
}
|
||||
return
|
||||
return cost
|
||||
}
|
||||
|
||||
func (s *Screen) updateCostBlank(to Line) (cost int) {
|
||||
@ -297,5 +297,5 @@ func (s *Screen) updateCostBlank(to Line) (cost int) {
|
||||
cost++
|
||||
}
|
||||
}
|
||||
return
|
||||
return cost
|
||||
}
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/cellbuf/link.go
generated
vendored
2
vendor/github.com/charmbracelet/x/cellbuf/link.go
generated
vendored
@ -4,7 +4,7 @@ import (
|
||||
"github.com/charmbracelet/colorprofile"
|
||||
)
|
||||
|
||||
// Convert converts a hyperlink to respect the given color profile.
|
||||
// ConvertLink converts a hyperlink to respect the given color profile.
|
||||
func ConvertLink(h Link, p colorprofile.Profile) Link {
|
||||
if p == colorprofile.NoTTY {
|
||||
return Link{}
|
||||
|
||||
92
vendor/github.com/charmbracelet/x/cellbuf/pen.go
generated
vendored
Normal file
92
vendor/github.com/charmbracelet/x/cellbuf/pen.go
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
package cellbuf
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
)
|
||||
|
||||
// PenWriter is a writer that writes to a buffer and keeps track of the current
|
||||
// pen style and link state for the purpose of wrapping with newlines.
|
||||
type PenWriter struct {
|
||||
w io.Writer
|
||||
p *ansi.Parser
|
||||
style Style
|
||||
link Link
|
||||
}
|
||||
|
||||
// NewPenWriter returns a new PenWriter.
|
||||
func NewPenWriter(w io.Writer) *PenWriter {
|
||||
pw := &PenWriter{w: w}
|
||||
pw.p = ansi.GetParser()
|
||||
handleCsi := func(cmd ansi.Cmd, params ansi.Params) {
|
||||
if cmd == 'm' {
|
||||
ReadStyle(params, &pw.style)
|
||||
}
|
||||
}
|
||||
handleOsc := func(cmd int, data []byte) {
|
||||
if cmd == 8 {
|
||||
ReadLink(data, &pw.link)
|
||||
}
|
||||
}
|
||||
pw.p.SetHandler(ansi.Handler{
|
||||
HandleCsi: handleCsi,
|
||||
HandleOsc: handleOsc,
|
||||
})
|
||||
return pw
|
||||
}
|
||||
|
||||
// Style returns the current pen style.
|
||||
func (w *PenWriter) Style() Style {
|
||||
return w.style
|
||||
}
|
||||
|
||||
// Link returns the current pen link.
|
||||
func (w *PenWriter) Link() Link {
|
||||
return w.link
|
||||
}
|
||||
|
||||
// Write writes to the buffer.
|
||||
func (w *PenWriter) Write(p []byte) (int, error) {
|
||||
for i := range p {
|
||||
b := p[i]
|
||||
w.p.Advance(b)
|
||||
if b == '\n' {
|
||||
if !w.style.Empty() {
|
||||
_, _ = w.w.Write([]byte(ansi.ResetStyle))
|
||||
}
|
||||
if !w.link.Empty() {
|
||||
_, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = w.w.Write([]byte{b})
|
||||
if b == '\n' {
|
||||
if !w.link.Empty() {
|
||||
_, _ = w.w.Write([]byte(ansi.SetHyperlink(w.link.URL, w.link.Params)))
|
||||
}
|
||||
if !w.style.Empty() {
|
||||
_, _ = w.w.Write([]byte(w.style.Sequence()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Close closes the writer, resets the style and link if necessary, and releases
|
||||
// its parser. Calling it is performance critical, but forgetting it does not
|
||||
// cause safety issues or leaks.
|
||||
func (w *PenWriter) Close() error {
|
||||
if !w.style.Empty() {
|
||||
_, _ = w.w.Write([]byte(ansi.ResetStyle))
|
||||
}
|
||||
if !w.link.Empty() {
|
||||
_, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
|
||||
}
|
||||
if w.p != nil {
|
||||
ansi.PutParser(w.p)
|
||||
w.p = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
221
vendor/github.com/charmbracelet/x/cellbuf/screen.go
generated
vendored
221
vendor/github.com/charmbracelet/x/cellbuf/screen.go
generated
vendored
@ -39,9 +39,9 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
var seq strings.Builder
|
||||
|
||||
width, height := s.newbuf.Width(), s.newbuf.Height()
|
||||
if ty != fy {
|
||||
if ty != fy { //nolint:nestif
|
||||
var yseq string
|
||||
if s.xtermLike && !s.opts.RelativeCursor {
|
||||
if s.caps.Contains(capVPA) && !s.opts.RelativeCursor {
|
||||
yseq = ansi.VerticalPositionAbsolute(ty + 1)
|
||||
}
|
||||
|
||||
@ -54,9 +54,13 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
}
|
||||
shouldScroll := !s.opts.AltScreen && fy+n >= s.scrollHeight
|
||||
if lf := strings.Repeat("\n", n); shouldScroll || (fy+n < height && len(lf) < len(yseq)) {
|
||||
//nolint:godox
|
||||
// TODO: Ensure we're not unintentionally scrolling the screen down.
|
||||
yseq = lf
|
||||
s.scrollHeight = max(s.scrollHeight, fy+n)
|
||||
if s.opts.MapNL {
|
||||
fx = 0
|
||||
}
|
||||
}
|
||||
} else if ty < fy {
|
||||
n := fy - ty
|
||||
@ -64,6 +68,7 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
yseq = cuu
|
||||
}
|
||||
if n == 1 && fy-1 > 0 {
|
||||
//nolint:godox
|
||||
// TODO: Ensure we're not unintentionally scrolling the screen up.
|
||||
yseq = ansi.ReverseIndex
|
||||
}
|
||||
@ -72,9 +77,9 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
seq.WriteString(yseq)
|
||||
}
|
||||
|
||||
if tx != fx {
|
||||
if tx != fx { //nolint:nestif
|
||||
var xseq string
|
||||
if s.xtermLike && !s.opts.RelativeCursor {
|
||||
if s.caps.Contains(capHPA) && !s.opts.RelativeCursor {
|
||||
xseq = ansi.HorizontalPositionAbsolute(tx + 1)
|
||||
}
|
||||
|
||||
@ -93,7 +98,8 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
if tabs > 0 {
|
||||
cht := ansi.CursorHorizontalForwardTab(tabs)
|
||||
tab := strings.Repeat("\t", tabs)
|
||||
if false && s.xtermLike && len(cht) < len(tab) {
|
||||
if false && s.caps.Contains(capCHT) && len(cht) < len(tab) {
|
||||
//nolint:godox
|
||||
// TODO: The linux console and some terminals such as
|
||||
// Alacritty don't support [ansi.CHT]. Enable this when
|
||||
// we have a way to detect this, or after 5 years when
|
||||
@ -144,7 +150,7 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
||||
}
|
||||
} else if tx < fx {
|
||||
n := fx - tx
|
||||
if useTabs && s.xtermLike {
|
||||
if useTabs && s.caps.Contains(capCBT) {
|
||||
// VT100 does not support backward tabs [ansi.CBT].
|
||||
|
||||
col := fx
|
||||
@ -190,7 +196,7 @@ func moveCursor(s *Screen, x, y int, overwrite bool) (seq string) {
|
||||
// Method #0: Use [ansi.CUP] if the distance is long.
|
||||
seq = ansi.CursorPosition(x+1, y+1)
|
||||
if fx == -1 || fy == -1 || notLocal(s.newbuf.Width(), fx, fy, x, y) {
|
||||
return
|
||||
return seq
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,7 +240,7 @@ func moveCursor(s *Screen, x, y int, overwrite bool) (seq string) {
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return seq
|
||||
}
|
||||
|
||||
// moveCursor moves the cursor to the specified position.
|
||||
@ -242,10 +248,10 @@ func (s *Screen) moveCursor(x, y int, overwrite bool) {
|
||||
if !s.opts.AltScreen && s.cur.X == -1 && s.cur.Y == -1 {
|
||||
// First cursor movement in inline mode, move the cursor to the first
|
||||
// column before moving to the target position.
|
||||
s.buf.WriteByte('\r') //nolint:errcheck
|
||||
s.buf.WriteByte('\r')
|
||||
s.cur.X, s.cur.Y = 0, 0
|
||||
}
|
||||
s.buf.WriteString(moveCursor(s, x, y, overwrite)) //nolint:errcheck
|
||||
s.buf.WriteString(moveCursor(s, x, y, overwrite))
|
||||
s.cur.X, s.cur.Y = x, y
|
||||
}
|
||||
|
||||
@ -274,10 +280,11 @@ func (s *Screen) move(x, y int) {
|
||||
// Reset wrap around (phantom cursor) state
|
||||
if s.atPhantom {
|
||||
s.cur.X = 0
|
||||
s.buf.WriteByte('\r') //nolint:errcheck
|
||||
s.atPhantom = false // reset phantom cell state
|
||||
s.buf.WriteByte('\r')
|
||||
s.atPhantom = false // reset phantom cell state
|
||||
}
|
||||
|
||||
//nolint:godox
|
||||
// TODO: Investigate if we need to handle this case and/or if we need the
|
||||
// following code.
|
||||
//
|
||||
@ -291,7 +298,7 @@ func (s *Screen) move(x, y int) {
|
||||
//
|
||||
// if l > 0 {
|
||||
// s.cur.X = 0
|
||||
// s.buf.WriteString("\r" + strings.Repeat("\n", l)) //nolint:errcheck
|
||||
// s.buf.WriteString("\r" + strings.Repeat("\n", l))
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -339,6 +346,10 @@ type ScreenOptions struct {
|
||||
HardTabs bool
|
||||
// Backspace is whether to use backspace characters to move the cursor.
|
||||
Backspace bool
|
||||
// MapNL whether we have ONLCR mapping enabled. When we set the terminal to
|
||||
// raw mode, the ONLCR mode gets disabled. ONLCR maps any newline/linefeed
|
||||
// (`\n`) character to carriage return + line feed (`\r\n`).
|
||||
MapNL bool
|
||||
}
|
||||
|
||||
// lineData represents the metadata for a line.
|
||||
@ -365,13 +376,13 @@ type Screen struct {
|
||||
opts ScreenOptions
|
||||
mu sync.Mutex
|
||||
method ansi.Method
|
||||
scrollHeight int // keeps track of how many lines we've scrolled down (inline mode)
|
||||
altScreenMode bool // whether alternate screen mode is enabled
|
||||
cursorHidden bool // whether text cursor mode is enabled
|
||||
clear bool // whether to force clear the screen
|
||||
xtermLike bool // whether to use xterm-like optimizations, otherwise, it uses vt100 only
|
||||
queuedText bool // whether we have queued non-zero width text queued up
|
||||
atPhantom bool // whether the cursor is out of bounds and at a phantom cell
|
||||
scrollHeight int // keeps track of how many lines we've scrolled down (inline mode)
|
||||
altScreenMode bool // whether alternate screen mode is enabled
|
||||
cursorHidden bool // whether text cursor mode is enabled
|
||||
clear bool // whether to force clear the screen
|
||||
caps capabilities // terminal control sequence capabilities
|
||||
queuedText bool // whether we have queued non-zero width text queued up
|
||||
atPhantom bool // whether the cursor is out of bounds and at a phantom cell
|
||||
}
|
||||
|
||||
// SetMethod sets the method used to calculate the width of cells.
|
||||
@ -491,36 +502,77 @@ func (s *Screen) FillRect(cell *Cell, r Rectangle) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// isXtermLike returns whether the terminal is xterm-like. This means that the
|
||||
// capabilities represents a mask of supported ANSI escape sequences.
|
||||
type capabilities uint
|
||||
|
||||
const (
|
||||
// Vertical Position Absolute [ansi.VPA].
|
||||
capVPA capabilities = 1 << iota
|
||||
// Horizontal Position Absolute [ansi.HPA].
|
||||
capHPA
|
||||
// Cursor Horizontal Tab [ansi.CHT].
|
||||
capCHT
|
||||
// Cursor Backward Tab [ansi.CBT].
|
||||
capCBT
|
||||
// Repeat Previous Character [ansi.REP].
|
||||
capREP
|
||||
// Erase Character [ansi.ECH].
|
||||
capECH
|
||||
// Insert Character [ansi.ICH].
|
||||
capICH
|
||||
// Scroll Down [ansi.SD].
|
||||
capSD
|
||||
// Scroll Up [ansi.SU].
|
||||
capSU
|
||||
|
||||
noCaps capabilities = 0
|
||||
allCaps = capVPA | capHPA | capCHT | capCBT | capREP | capECH | capICH |
|
||||
capSD | capSU
|
||||
)
|
||||
|
||||
// Contains returns whether the capabilities contains the given capability.
|
||||
func (v capabilities) Contains(c capabilities) bool {
|
||||
return v&c == c
|
||||
}
|
||||
|
||||
// xtermCaps returns whether the terminal is xterm-like. This means that the
|
||||
// terminal supports ECMA-48 and ANSI X3.64 escape sequences.
|
||||
// TODO: Should this be a lookup table into each $TERM terminfo database? Like
|
||||
// we could keep a map of ANSI escape sequence to terminfo capability name and
|
||||
// check if the database supports the escape sequence. Instead of keeping a
|
||||
// list of terminal names here.
|
||||
func isXtermLike(termtype string) (v bool) {
|
||||
// xtermCaps returns a list of control sequence capabilities for the given
|
||||
// terminal type. This only supports a subset of sequences that can
|
||||
// be different among terminals.
|
||||
// NOTE: A hybrid approach would be to support Terminfo databases for a full
|
||||
// set of capabilities.
|
||||
func xtermCaps(termtype string) (v capabilities) {
|
||||
parts := strings.Split(termtype, "-")
|
||||
if len(parts) == 0 {
|
||||
return
|
||||
return v
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
case
|
||||
"alacritty",
|
||||
"contour",
|
||||
"foot",
|
||||
"ghostty",
|
||||
"kitty",
|
||||
"linux",
|
||||
"rio",
|
||||
"screen",
|
||||
"st",
|
||||
"tmux",
|
||||
"wezterm",
|
||||
"xterm":
|
||||
v = true
|
||||
v = allCaps
|
||||
case "alacritty":
|
||||
v = allCaps
|
||||
v &^= capCHT // NOTE: alacritty added support for [ansi.CHT] in 2024-12-28 #62d5b13.
|
||||
case "screen":
|
||||
// See https://www.gnu.org/software/screen/manual/screen.html#Control-Sequences-1
|
||||
v = allCaps
|
||||
v &^= capREP
|
||||
case "linux":
|
||||
// See https://man7.org/linux/man-pages/man4/console_codes.4.html
|
||||
v = capVPA | capHPA | capECH | capICH
|
||||
}
|
||||
|
||||
return
|
||||
return v
|
||||
}
|
||||
|
||||
// NewScreen creates a new Screen.
|
||||
@ -548,14 +600,14 @@ func NewScreen(w io.Writer, width, height int, opts *ScreenOptions) (s *Screen)
|
||||
}
|
||||
|
||||
s.buf = new(bytes.Buffer)
|
||||
s.xtermLike = isXtermLike(s.opts.Term)
|
||||
s.caps = xtermCaps(s.opts.Term)
|
||||
s.curbuf = NewBuffer(width, height)
|
||||
s.newbuf = NewBuffer(width, height)
|
||||
s.cur = Cursor{Position: Pos(-1, -1)} // start at -1 to force a move
|
||||
s.saved = s.cur
|
||||
s.reset()
|
||||
|
||||
return
|
||||
return s
|
||||
}
|
||||
|
||||
// Width returns the width of the screen.
|
||||
@ -595,7 +647,7 @@ func (s *Screen) putCell(cell *Cell) {
|
||||
|
||||
// wrapCursor wraps the cursor to the next line.
|
||||
//
|
||||
//nolint:unused
|
||||
|
||||
func (s *Screen) wrapCursor() {
|
||||
const autoRightMargin = true
|
||||
if autoRightMargin {
|
||||
@ -628,9 +680,9 @@ func (s *Screen) putAttrCell(cell *Cell) {
|
||||
}
|
||||
|
||||
s.updatePen(cell)
|
||||
s.buf.WriteRune(cell.Rune) //nolint:errcheck
|
||||
s.buf.WriteRune(cell.Rune)
|
||||
for _, c := range cell.Comb {
|
||||
s.buf.WriteRune(c) //nolint:errcheck
|
||||
s.buf.WriteRune(c)
|
||||
}
|
||||
|
||||
s.cur.X += cell.Width
|
||||
@ -649,12 +701,12 @@ func (s *Screen) putCellLR(cell *Cell) {
|
||||
// Optimize for the lower right corner cell.
|
||||
curX := s.cur.X
|
||||
if cell == nil || !cell.Empty() {
|
||||
s.buf.WriteString(ansi.ResetAutoWrapMode) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.ResetModeAutoWrap)
|
||||
s.putAttrCell(cell)
|
||||
// Writing to lower-right corner cell should not wrap.
|
||||
s.atPhantom = false
|
||||
s.cur.X = curX
|
||||
s.buf.WriteString(ansi.SetAutoWrapMode) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.SetModeAutoWrap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,11 +727,11 @@ func (s *Screen) updatePen(cell *Cell) {
|
||||
if cell.Style.Empty() && len(seq) > len(ansi.ResetStyle) {
|
||||
seq = ansi.ResetStyle
|
||||
}
|
||||
s.buf.WriteString(seq) //nolint:errcheck
|
||||
s.buf.WriteString(seq)
|
||||
s.cur.Style = cell.Style
|
||||
}
|
||||
if !cell.Link.Equal(&s.cur.Link) {
|
||||
s.buf.WriteString(ansi.SetHyperlink(cell.Link.URL, cell.Link.Params)) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.SetHyperlink(cell.Link.URL, cell.Link.Params))
|
||||
s.cur.Link = cell.Link
|
||||
}
|
||||
}
|
||||
@ -712,9 +764,9 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
||||
ech := ansi.EraseCharacter(count)
|
||||
cup := ansi.CursorPosition(s.cur.X+count, s.cur.Y)
|
||||
rep := ansi.RepeatPreviousCharacter(count)
|
||||
if s.xtermLike && count > len(ech)+len(cup) && cell0 != nil && cell0.Clear() {
|
||||
if s.caps.Contains(capECH) && count > len(ech)+len(cup) && cell0 != nil && cell0.Clear() { //nolint:nestif
|
||||
s.updatePen(cell0)
|
||||
s.buf.WriteString(ech) //nolint:errcheck
|
||||
s.buf.WriteString(ech)
|
||||
|
||||
// If this is the last cell, we don't need to move the cursor.
|
||||
if count < n {
|
||||
@ -722,7 +774,7 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
||||
} else {
|
||||
return true // cursor in the middle
|
||||
}
|
||||
} else if s.xtermLike && count > len(rep) &&
|
||||
} else if s.caps.Contains(capREP) && count > len(rep) &&
|
||||
(cell0 == nil || (len(cell0.Comb) == 0 && cell0.Rune < 256)) {
|
||||
// We only support ASCII characters. Most terminals will handle
|
||||
// non-ASCII characters correctly, but some might not, ahem xterm.
|
||||
@ -740,13 +792,13 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
||||
s.putCell(cell0)
|
||||
repCount-- // cell0 is a single width cell ASCII character
|
||||
|
||||
s.buf.WriteString(ansi.RepeatPreviousCharacter(repCount)) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.RepeatPreviousCharacter(repCount))
|
||||
s.cur.X += repCount
|
||||
if wrapPossible {
|
||||
s.putCell(cell0)
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < count; i++ {
|
||||
for i := range count {
|
||||
s.putCell(line.At(i))
|
||||
}
|
||||
}
|
||||
@ -755,7 +807,7 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
||||
n -= count
|
||||
}
|
||||
|
||||
return
|
||||
return eoi
|
||||
}
|
||||
|
||||
// putRange puts a range of cells from the old line to the new line.
|
||||
@ -765,7 +817,7 @@ func (s *Screen) putRange(oldLine, newLine Line, y, start, end int) (eoi bool) {
|
||||
inline := min(len(ansi.CursorPosition(start+1, y+1)),
|
||||
min(len(ansi.HorizontalPositionAbsolute(start+1)),
|
||||
len(ansi.CursorForward(start+1))))
|
||||
if (end - start + 1) > inline {
|
||||
if (end - start + 1) > inline { //nolint:nestif
|
||||
var j, same int
|
||||
for j, same = start, 0; j <= end; j++ {
|
||||
oldCell, newCell := oldLine.At(j), newLine.At(j)
|
||||
@ -817,9 +869,9 @@ func (s *Screen) clearToEnd(blank *Cell, force bool) { //nolint:unparam
|
||||
s.updatePen(blank)
|
||||
count := s.newbuf.Width() - s.cur.X
|
||||
if s.el0Cost() <= count {
|
||||
s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.EraseLineRight)
|
||||
} else {
|
||||
for i := 0; i < count; i++ {
|
||||
for range count {
|
||||
s.putCell(blank)
|
||||
}
|
||||
}
|
||||
@ -839,12 +891,13 @@ func (s *Screen) clearBlank() *Cell {
|
||||
// insertCells inserts the count cells pointed by the given line at the current
|
||||
// cursor position.
|
||||
func (s *Screen) insertCells(line Line, count int) {
|
||||
if s.xtermLike {
|
||||
supportsICH := s.caps.Contains(capICH)
|
||||
if supportsICH {
|
||||
// Use [ansi.ICH] as an optimization.
|
||||
s.buf.WriteString(ansi.InsertCharacter(count)) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.InsertCharacter(count))
|
||||
} else {
|
||||
// Otherwise, use [ansi.IRM] mode.
|
||||
s.buf.WriteString(ansi.SetInsertReplaceMode) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.SetModeInsertReplace)
|
||||
}
|
||||
|
||||
for i := 0; count > 0; i++ {
|
||||
@ -852,8 +905,8 @@ func (s *Screen) insertCells(line Line, count int) {
|
||||
count--
|
||||
}
|
||||
|
||||
if !s.xtermLike {
|
||||
s.buf.WriteString(ansi.ResetInsertReplaceMode) //nolint:errcheck
|
||||
if !supportsICH {
|
||||
s.buf.WriteString(ansi.ResetModeInsertReplace)
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,7 +915,7 @@ func (s *Screen) insertCells(line Line, count int) {
|
||||
// [ansi.EL] 0 i.e. [ansi.EraseLineRight] to clear
|
||||
// trailing spaces.
|
||||
func (s *Screen) el0Cost() int {
|
||||
if s.xtermLike {
|
||||
if s.caps != noCaps {
|
||||
return 0
|
||||
}
|
||||
return len(ansi.EraseLineRight)
|
||||
@ -878,7 +931,7 @@ func (s *Screen) transformLine(y int) {
|
||||
|
||||
// Find the first changed cell in the line
|
||||
var lineChanged bool
|
||||
for i := 0; i < s.newbuf.Width(); i++ {
|
||||
for i := range s.newbuf.Width() {
|
||||
if !cellEqual(newLine.At(i), oldLine.At(i)) {
|
||||
lineChanged = true
|
||||
break
|
||||
@ -886,7 +939,7 @@ func (s *Screen) transformLine(y int) {
|
||||
}
|
||||
|
||||
const ceolStandoutGlitch = false
|
||||
if ceolStandoutGlitch && lineChanged {
|
||||
if ceolStandoutGlitch && lineChanged { //nolint:nestif
|
||||
s.move(0, y)
|
||||
s.clearToEnd(nil, false)
|
||||
s.putRange(oldLine, newLine, y, 0, s.newbuf.Width()-1)
|
||||
@ -897,12 +950,12 @@ func (s *Screen) transformLine(y int) {
|
||||
// [ansi.EraseLineLeft].
|
||||
if blank == nil || blank.Clear() {
|
||||
var oFirstCell, nFirstCell int
|
||||
for oFirstCell = 0; oFirstCell < s.curbuf.Width(); oFirstCell++ {
|
||||
for oFirstCell = range s.curbuf.Width() {
|
||||
if !cellEqual(oldLine.At(oFirstCell), blank) {
|
||||
break
|
||||
}
|
||||
}
|
||||
for nFirstCell = 0; nFirstCell < s.newbuf.Width(); nFirstCell++ {
|
||||
for nFirstCell = range s.newbuf.Width() {
|
||||
if !cellEqual(newLine.At(nFirstCell), blank) {
|
||||
break
|
||||
}
|
||||
@ -925,11 +978,11 @@ func (s *Screen) transformLine(y int) {
|
||||
if nFirstCell >= s.newbuf.Width() {
|
||||
s.move(0, y)
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.EraseLineRight)
|
||||
} else {
|
||||
s.move(nFirstCell-1, y)
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.EraseLineLeft) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.EraseLineLeft)
|
||||
}
|
||||
|
||||
for firstCell < nFirstCell {
|
||||
@ -1045,7 +1098,7 @@ func (s *Screen) transformLine(y int) {
|
||||
|
||||
s.move(n+1, y)
|
||||
ichCost := 3 + nLastCell - oLastCell
|
||||
if s.xtermLike && (nLastCell < nLastNonBlank || ichCost > (m-n)) {
|
||||
if s.caps.Contains(capICH) && (nLastCell < nLastNonBlank || ichCost > (m-n)) {
|
||||
s.putRange(oldLine, newLine, y, n+1, m)
|
||||
} else {
|
||||
s.insertCells(newLine[n+1:], nLastCell-oLastCell)
|
||||
@ -1079,7 +1132,7 @@ func (s *Screen) transformLine(y int) {
|
||||
func (s *Screen) deleteCells(count int) {
|
||||
// [ansi.DCH] will shift in cells from the right margin so we need to
|
||||
// ensure that they are the right style.
|
||||
s.buf.WriteString(ansi.DeleteCharacter(count)) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.DeleteCharacter(count))
|
||||
}
|
||||
|
||||
// clearToBottom clears the screen from the current cursor position to the end
|
||||
@ -1091,7 +1144,7 @@ func (s *Screen) clearToBottom(blank *Cell) {
|
||||
}
|
||||
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.EraseScreenBelow) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.EraseScreenBelow)
|
||||
// Clear the rest of the current line
|
||||
s.curbuf.ClearRect(Rect(col, row, s.curbuf.Width()-col, 1))
|
||||
// Clear everything below the current line
|
||||
@ -1104,7 +1157,7 @@ func (s *Screen) clearToBottom(blank *Cell) {
|
||||
// It returns the top line.
|
||||
func (s *Screen) clearBottom(total int) (top int) {
|
||||
if total <= 0 {
|
||||
return
|
||||
return top
|
||||
}
|
||||
|
||||
top = total
|
||||
@ -1112,7 +1165,7 @@ func (s *Screen) clearBottom(total int) (top int) {
|
||||
blank := s.clearBlank()
|
||||
canClearWithBlank := blank == nil || blank.Clear()
|
||||
|
||||
if canClearWithBlank {
|
||||
if canClearWithBlank { //nolint:nestif
|
||||
var row int
|
||||
for row = total - 1; row >= 0; row-- {
|
||||
oldLine := s.curbuf.Line(row)
|
||||
@ -1147,14 +1200,14 @@ func (s *Screen) clearBottom(total int) (top int) {
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return top
|
||||
}
|
||||
|
||||
// clearScreen clears the screen and put cursor at home.
|
||||
func (s *Screen) clearScreen(blank *Cell) {
|
||||
s.updatePen(blank)
|
||||
s.buf.WriteString(ansi.CursorHomePosition) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.EraseEntireScreen) //nolint:errcheck
|
||||
s.buf.WriteString(ansi.CursorHomePosition)
|
||||
s.buf.WriteString(ansi.EraseEntireScreen)
|
||||
s.cur.X, s.cur.Y = 0, 0
|
||||
s.curbuf.Fill(blank)
|
||||
}
|
||||
@ -1179,7 +1232,7 @@ func (s *Screen) clearUpdate() {
|
||||
s.clearBelow(blank, 0)
|
||||
}
|
||||
nonEmpty = s.clearBottom(nonEmpty)
|
||||
for i := 0; i < nonEmpty; i++ {
|
||||
for i := range nonEmpty {
|
||||
s.transformLine(i)
|
||||
}
|
||||
}
|
||||
@ -1194,13 +1247,13 @@ func (s *Screen) Flush() (err error) {
|
||||
func (s *Screen) flush() (err error) {
|
||||
// Write the buffer
|
||||
if s.buf.Len() > 0 {
|
||||
_, err = s.w.Write(s.buf.Bytes()) //nolint:errcheck
|
||||
_, err = s.w.Write(s.buf.Bytes())
|
||||
if err == nil {
|
||||
s.buf.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
// Render renders changes of the screen to the internal buffer. Call
|
||||
@ -1221,6 +1274,7 @@ func (s *Screen) render() {
|
||||
return
|
||||
}
|
||||
|
||||
//nolint:godox
|
||||
// TODO: Investigate whether this is necessary. Theoretically, terminals
|
||||
// can add/remove tab stops and we should be able to handle that. We could
|
||||
// use [ansi.DECTABSR] to read the tab stops, but that's not implemented in
|
||||
@ -1235,9 +1289,9 @@ func (s *Screen) render() {
|
||||
// Do we need alt-screen mode?
|
||||
if s.opts.AltScreen != s.altScreenMode {
|
||||
if s.opts.AltScreen {
|
||||
s.buf.WriteString(ansi.SetAltScreenSaveCursorMode)
|
||||
s.buf.WriteString(ansi.SetModeAltScreenSaveCursor)
|
||||
} else {
|
||||
s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode)
|
||||
s.buf.WriteString(ansi.ResetModeAltScreenSaveCursor)
|
||||
}
|
||||
s.altScreenMode = s.opts.AltScreen
|
||||
}
|
||||
@ -1252,7 +1306,9 @@ func (s *Screen) render() {
|
||||
|
||||
// Do we have queued strings to write above the screen?
|
||||
if len(s.queueAbove) > 0 {
|
||||
//nolint:godox
|
||||
// TODO: Use scrolling region if available.
|
||||
//nolint:godox
|
||||
// TODO: Use [Screen.Write] [io.Writer] interface.
|
||||
|
||||
// We need to scroll the screen up by the number of lines in the queue.
|
||||
@ -1290,12 +1346,13 @@ func (s *Screen) render() {
|
||||
s.clearBelow(nil, s.newbuf.Height()-1)
|
||||
}
|
||||
|
||||
if s.clear {
|
||||
if s.clear { //nolint:nestif
|
||||
s.clearUpdate()
|
||||
s.clear = false
|
||||
} else if len(s.touch) > 0 {
|
||||
if s.opts.AltScreen {
|
||||
// Optimize scrolling for the alternate screen buffer.
|
||||
//nolint:godox
|
||||
// TODO: Should we optimize for inline mode as well? If so, we need
|
||||
// to know the actual cursor position to use [ansi.DECSTBM].
|
||||
s.scrollOptimize()
|
||||
@ -1311,7 +1368,7 @@ func (s *Screen) render() {
|
||||
}
|
||||
|
||||
nonEmpty = s.clearBottom(nonEmpty)
|
||||
for i = 0; i < nonEmpty; i++ {
|
||||
for i = range nonEmpty {
|
||||
_, ok := s.touch[i]
|
||||
if ok {
|
||||
s.transformLine(i)
|
||||
@ -1359,7 +1416,7 @@ func (s *Screen) Close() (err error) {
|
||||
s.move(0, s.newbuf.Height()-1)
|
||||
|
||||
if s.altScreenMode {
|
||||
s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode)
|
||||
s.buf.WriteString(ansi.ResetModeAltScreenSaveCursor)
|
||||
s.altScreenMode = false
|
||||
}
|
||||
|
||||
@ -1371,11 +1428,11 @@ func (s *Screen) Close() (err error) {
|
||||
// Write the buffer
|
||||
err = s.flush()
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
s.reset()
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// reset resets the screen to its initial state.
|
||||
@ -1420,9 +1477,9 @@ func (s *Screen) Resize(width, height int) bool {
|
||||
}
|
||||
|
||||
if height > oldh {
|
||||
s.ClearRect(Rect(0, max(oldh-1, 0), width, height-oldh))
|
||||
s.ClearRect(Rect(0, max(oldh, 0), width, height-oldh))
|
||||
} else if height < oldh {
|
||||
s.ClearRect(Rect(0, max(height-1, 0), width, oldh-height))
|
||||
s.ClearRect(Rect(0, max(height, 0), width, oldh-height))
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
|
||||
4
vendor/github.com/charmbracelet/x/cellbuf/style.go
generated
vendored
4
vendor/github.com/charmbracelet/x/cellbuf/style.go
generated
vendored
@ -4,9 +4,9 @@ import (
|
||||
"github.com/charmbracelet/colorprofile"
|
||||
)
|
||||
|
||||
// Convert converts a style to respect the given color profile.
|
||||
// ConvertStyle converts a style to respect the given color profile.
|
||||
func ConvertStyle(s Style, p colorprofile.Profile) Style {
|
||||
switch p {
|
||||
switch p { //nolint:exhaustive
|
||||
case colorprofile.TrueColor:
|
||||
return s
|
||||
case colorprofile.Ascii:
|
||||
|
||||
14
vendor/github.com/charmbracelet/x/cellbuf/utils.go
generated
vendored
14
vendor/github.com/charmbracelet/x/cellbuf/utils.go
generated
vendored
@ -9,20 +9,6 @@ func Height(s string) int {
|
||||
return strings.Count(s, "\n") + 1
|
||||
}
|
||||
|
||||
func min(a, b int) int { //nolint:predeclared
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func max(a, b int) int { //nolint:predeclared
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func clamp(v, low, high int) int {
|
||||
if high < low {
|
||||
low, high = high, low
|
||||
|
||||
20
vendor/github.com/charmbracelet/x/cellbuf/wrap.go
generated
vendored
20
vendor/github.com/charmbracelet/x/cellbuf/wrap.go
generated
vendored
@ -2,6 +2,7 @@ package cellbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"slices"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
@ -20,6 +21,16 @@ const nbsp = '\u00a0'
|
||||
//
|
||||
// Note: breakpoints must be a string of 1-cell wide rune characters.
|
||||
func Wrap(s string, limit int, breakpoints string) string {
|
||||
//nolint:godox
|
||||
// TODO: Use [PenWriter] once we get
|
||||
// https://github.com/charmbracelet/lipgloss/pull/489 out the door and
|
||||
// released.
|
||||
// The problem is that [ansi.Wrap] doesn't keep track of style and link
|
||||
// state, so combining both breaks styled space cells. To fix this, we use
|
||||
// non-breaking space cells for padding and styled blank cells. And since
|
||||
// both wrapping methods respect non-breaking spaces, we can use them to
|
||||
// preserve styled spaces in the output.
|
||||
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -90,7 +101,7 @@ func Wrap(s string, limit int, breakpoints string) string {
|
||||
seq, width, n, newState := ansi.DecodeSequence(s, state, p)
|
||||
switch width {
|
||||
case 0:
|
||||
if ansi.Equal(seq, "\t") {
|
||||
if ansi.Equal(seq, "\t") { //nolint:nestif
|
||||
addWord()
|
||||
space.WriteString(seq)
|
||||
break
|
||||
@ -176,10 +187,5 @@ func Wrap(s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
func runeContainsAny[T string | []rune](r rune, s T) bool {
|
||||
for _, c := range []rune(s) {
|
||||
if c == r {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains([]rune(s), r)
|
||||
}
|
||||
|
||||
29
vendor/github.com/charmbracelet/x/cellbuf/writer.go
generated
vendored
29
vendor/github.com/charmbracelet/x/cellbuf/writer.go
generated
vendored
@ -25,7 +25,7 @@ type CellBuffer interface {
|
||||
func FillRect(s CellBuffer, c *Cell, rect Rectangle) {
|
||||
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||
for x := rect.Min.X; x < rect.Max.X; x++ {
|
||||
s.SetCell(x, y, c) //nolint:errcheck
|
||||
s.SetCell(x, y, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ func SetContent(s CellBuffer, str string) {
|
||||
func Render(d CellBuffer) string {
|
||||
var buf bytes.Buffer
|
||||
height := d.Bounds().Dy()
|
||||
for y := 0; y < height; y++ {
|
||||
for y := range height {
|
||||
_, line := RenderLine(d, y)
|
||||
buf.WriteString(line)
|
||||
if y < height-1 {
|
||||
@ -98,32 +98,32 @@ func RenderLine(d CellBuffer, n int) (w int, line string) {
|
||||
pendingLine = ""
|
||||
}
|
||||
|
||||
for x := 0; x < d.Bounds().Dx(); x++ {
|
||||
if cell := d.Cell(x, n); cell != nil && cell.Width > 0 {
|
||||
for x := range d.Bounds().Dx() {
|
||||
if cell := d.Cell(x, n); cell != nil && cell.Width > 0 { //nolint:nestif
|
||||
// Convert the cell's style and link to the given color profile.
|
||||
cellStyle := cell.Style
|
||||
cellLink := cell.Link
|
||||
if cellStyle.Empty() && !pen.Empty() {
|
||||
writePending()
|
||||
buf.WriteString(ansi.ResetStyle) //nolint:errcheck
|
||||
buf.WriteString(ansi.ResetStyle)
|
||||
pen.Reset()
|
||||
}
|
||||
if !cellStyle.Equal(&pen) {
|
||||
writePending()
|
||||
seq := cellStyle.DiffSequence(pen)
|
||||
buf.WriteString(seq) // nolint:errcheck
|
||||
buf.WriteString(seq)
|
||||
pen = cellStyle
|
||||
}
|
||||
|
||||
// Write the URL escape sequence
|
||||
if cellLink != link && link.URL != "" {
|
||||
writePending()
|
||||
buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck
|
||||
buf.WriteString(ansi.ResetHyperlink())
|
||||
link.Reset()
|
||||
}
|
||||
if cellLink != link {
|
||||
writePending()
|
||||
buf.WriteString(ansi.SetHyperlink(cellLink.URL, cellLink.Params)) //nolint:errcheck
|
||||
buf.WriteString(ansi.SetHyperlink(cellLink.URL, cellLink.Params))
|
||||
link = cellLink
|
||||
}
|
||||
|
||||
@ -140,10 +140,10 @@ func RenderLine(d CellBuffer, n int) (w int, line string) {
|
||||
}
|
||||
}
|
||||
if link.URL != "" {
|
||||
buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck
|
||||
buf.WriteString(ansi.ResetHyperlink())
|
||||
}
|
||||
if !pen.Empty() {
|
||||
buf.WriteString(ansi.ResetStyle) //nolint:errcheck
|
||||
buf.WriteString(ansi.ResetStyle)
|
||||
}
|
||||
return w, strings.TrimRight(buf.String(), " ") // Trim trailing spaces
|
||||
}
|
||||
@ -201,7 +201,7 @@ func (s *ScreenWriter) SetContentRect(str string, rect Rectangle) {
|
||||
// string to the width of the screen if it exceeds the width of the screen.
|
||||
// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape
|
||||
// sequences.
|
||||
func (s *ScreenWriter) Print(str string, v ...interface{}) {
|
||||
func (s *ScreenWriter) Print(str string, v ...any) {
|
||||
if len(v) > 0 {
|
||||
str = fmt.Sprintf(str, v...)
|
||||
}
|
||||
@ -214,7 +214,7 @@ func (s *ScreenWriter) Print(str string, v ...interface{}) {
|
||||
// the width of the screen if it exceeds the width of the screen.
|
||||
// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape
|
||||
// sequences.
|
||||
func (s *ScreenWriter) PrintAt(x, y int, str string, v ...interface{}) {
|
||||
func (s *ScreenWriter) PrintAt(x, y int, str string, v ...any) {
|
||||
if len(v) > 0 {
|
||||
str = fmt.Sprintf(str, v...)
|
||||
}
|
||||
@ -299,7 +299,7 @@ func printString[T []byte | string](
|
||||
// Print the cell to the screen
|
||||
cell.Style = style
|
||||
cell.Link = link
|
||||
s.SetCell(x, y, &cell) //nolint:errcheck
|
||||
s.SetCell(x, y, &cell)
|
||||
x += width
|
||||
}
|
||||
}
|
||||
@ -309,6 +309,7 @@ func printString[T []byte | string](
|
||||
cell.Reset()
|
||||
default:
|
||||
// Valid sequences always have a non-zero Cmd.
|
||||
//nolint:godox
|
||||
// TODO: Handle cursor movement and other sequences
|
||||
switch {
|
||||
case ansi.HasCsiPrefix(seq) && p.Command() == 'm':
|
||||
@ -333,7 +334,7 @@ func printString[T []byte | string](
|
||||
|
||||
// Make sure to set the last cell if it's not empty.
|
||||
if !cell.Empty() {
|
||||
s.SetCell(x, y, &cell) //nolint:errcheck
|
||||
s.SetCell(x, y, &cell)
|
||||
cell.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/term/term.go
generated
vendored
2
vendor/github.com/charmbracelet/x/term/term.go
generated
vendored
@ -1,3 +1,5 @@
|
||||
// Package term provides a platform-independent interfaces for interacting with
|
||||
// Terminal and TTY devices.
|
||||
package term
|
||||
|
||||
// State contains platform-specific state of a terminal.
|
||||
|
||||
118
vendor/github.com/charmbracelet/x/term/term_plan9.go
generated
vendored
Normal file
118
vendor/github.com/charmbracelet/x/term/term_plan9.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type state struct {
|
||||
termName string
|
||||
raw bool
|
||||
ctl *os.File
|
||||
}
|
||||
|
||||
// termName returns the name of the terminal or os.ErrNotExist if there is no terminal.
|
||||
func termName(fd uintptr) (string, error) {
|
||||
ctl, err := os.ReadFile(filepath.Join("/fd", fmt.Sprintf("%dctl", fd)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
f := strings.Fields(string(ctl))
|
||||
if len(f) == 0 {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
return f[len(f)-1], nil
|
||||
}
|
||||
|
||||
func isTerminal(fd uintptr) bool {
|
||||
ctl, err := os.ReadFile(filepath.Join("/fd", fmt.Sprintf("%dctl", fd)))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(string(ctl), "/dev/cons") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func makeRaw(fd uintptr) (*State, error) {
|
||||
t, err := termName(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctl, err := os.OpenFile(t, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := ctl.Write([]byte("rawon")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &State{state: state{termName: t, raw: true, ctl: ctl}}, nil
|
||||
}
|
||||
|
||||
func getState(fd uintptr) (*State, error) {
|
||||
t, err := termName(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctl, err := os.OpenFile(t, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &State{state: state{termName: t, raw: false, ctl: ctl}}, nil
|
||||
|
||||
}
|
||||
|
||||
func restore(_ uintptr, state *State) error {
|
||||
if _, err := state.ctl.Write([]byte("rawoff")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSize returns the size. This will only work if you are running
|
||||
// under a window manager in Plan 9. Else, the only option
|
||||
// is to return a reasonable default.
|
||||
func getSize(fd uintptr) (int, int, error) {
|
||||
w, h := 80, 40
|
||||
b, err := os.ReadFile("/dev/wctl")
|
||||
if err != nil {
|
||||
return w, h, err
|
||||
}
|
||||
f := strings.Fields(string(b))
|
||||
if len(f) != 4 {
|
||||
return w, h, fmt.Errorf("%q only has %d of 4 needed fields:%w", f, len(f), os.ErrInvalid)
|
||||
}
|
||||
// The contents of wctl, as defined in the driver, are
|
||||
// 4 12-char fields: upper left x, y; and lower-right x, y
|
||||
var ulx, uly, lrx, lry int
|
||||
if n, err := fmt.Sscanf(string(b[:48]), "%d%d%d%d", &ulx, &uly, &lrx, &lry); n != 4 || err != nil {
|
||||
return w, h, fmt.Errorf("scanning %q:%d of 4 items scanned:%w", string(b[:48]), n, err)
|
||||
}
|
||||
|
||||
w, h = lrx-lrx, lry-uly
|
||||
return w, h, nil
|
||||
}
|
||||
|
||||
func setState(_ uintptr, state *State) error {
|
||||
raw := "rawoff"
|
||||
if state.raw {
|
||||
raw = "rawon"
|
||||
}
|
||||
if _, err := state.ctl.Write([]byte(raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readPassword(fd uintptr) ([]byte, error) {
|
||||
f := os.NewFile(fd, "cons")
|
||||
var b [128]byte
|
||||
n, err := f.Read(b[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
20
vendor/github.com/charmbracelet/x/term/term_unix.go
generated
vendored
20
vendor/github.com/charmbracelet/x/term/term_unix.go
generated
vendored
@ -19,7 +19,7 @@ func isTerminal(fd uintptr) bool {
|
||||
func makeRaw(fd uintptr) (*State, error) {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
oldState := State{state{Termios: *termios}}
|
||||
@ -34,7 +34,7 @@ func makeRaw(fd uintptr) (*State, error) {
|
||||
termios.Cc[unix.VMIN] = 1
|
||||
termios.Cc[unix.VTIME] = 0
|
||||
if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios); err != nil {
|
||||
return nil, err
|
||||
return nil, err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
@ -45,26 +45,26 @@ func setState(fd uintptr, state *State) error {
|
||||
if state != nil {
|
||||
termios = &state.Termios
|
||||
}
|
||||
return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios)
|
||||
return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) //nolint:wrapcheck
|
||||
}
|
||||
|
||||
func getState(fd uintptr) (*State, error) {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
return &State{state{Termios: *termios}}, nil
|
||||
}
|
||||
|
||||
func restore(fd uintptr, state *State) error {
|
||||
return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.Termios)
|
||||
return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.Termios) //nolint:wrapcheck
|
||||
}
|
||||
|
||||
func getSize(fd uintptr) (width, height int, err error) {
|
||||
ws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, err //nolint:wrapcheck
|
||||
}
|
||||
return int(ws.Col), int(ws.Row), nil
|
||||
}
|
||||
@ -73,13 +73,13 @@ func getSize(fd uintptr) (width, height int, err error) {
|
||||
type passwordReader int
|
||||
|
||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||
return unix.Read(int(r), buf)
|
||||
return unix.Read(int(r), buf) //nolint:wrapcheck
|
||||
}
|
||||
|
||||
func readPassword(fd uintptr) ([]byte, error) {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
newState := *termios
|
||||
@ -87,10 +87,10 @@ func readPassword(fd uintptr) ([]byte, error) {
|
||||
newState.Lflag |= unix.ICANON | unix.ISIG
|
||||
newState.Iflag |= unix.ICRNL
|
||||
if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &newState); err != nil {
|
||||
return nil, err
|
||||
return nil, err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
defer unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios)
|
||||
defer unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) //nolint:errcheck
|
||||
|
||||
return readPasswordLine(passwordReader(fd))
|
||||
}
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/term/term_windows.go
generated
vendored
2
vendor/github.com/charmbracelet/x/term/term_windows.go
generated
vendored
@ -24,7 +24,7 @@ func makeRaw(fd uintptr) (*State, error) {
|
||||
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
|
||||
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT)
|
||||
raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
|
||||
return nil, err
|
||||
|
||||
2
vendor/github.com/charmbracelet/x/term/util.go
generated
vendored
2
vendor/github.com/charmbracelet/x/term/util.go
generated
vendored
@ -41,7 +41,7 @@ func readPasswordLine(reader io.Reader) ([]byte, error) {
|
||||
if err == io.EOF && len(ret) > 0 {
|
||||
return ret, nil
|
||||
}
|
||||
return ret, err
|
||||
return ret, err //nolint:wrapcheck
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
vendor/github.com/clipperhouse/displaywidth/.gitignore
generated
vendored
Normal file
3
vendor/github.com/clipperhouse/displaywidth/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
*.out
|
||||
*.test
|
||||
51
vendor/github.com/clipperhouse/displaywidth/AGENTS.md
generated
vendored
Normal file
51
vendor/github.com/clipperhouse/displaywidth/AGENTS.md
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
The goals and overview of this package can be found in the README.md file,
|
||||
start by reading that.
|
||||
|
||||
The goal of this package is to determine the display (column) width of a
|
||||
string, UTF-8 bytes, or runes, as would happen in a monospace font, especially
|
||||
in a terminal.
|
||||
|
||||
When troubleshooting, write Go unit tests instead of executing debug scripts.
|
||||
The tests can return whatever logs or output you need. If those tests are
|
||||
only for temporary troubleshooting, clean up the tests after the debugging is
|
||||
done.
|
||||
|
||||
(Separate executable debugging scripts are messy, tend to have conflicting
|
||||
dependencies and are hard to cleanup.)
|
||||
|
||||
If you make changes to the trie generation in internal/gen, it can be invoked
|
||||
by running `go generate` from the top package directory.
|
||||
|
||||
## Pull Requests and branches
|
||||
|
||||
For PRs (pull requests), you can use the gh CLI tool. Compare the current branch with main. Reviewing a PR and reviewing a branch are about the same, but the PR may add context.
|
||||
|
||||
Understand the goals of the PR. Note any API changes, especially breaking changes.
|
||||
|
||||
Look for thoroughness of tests, as well as GoDoc comments.
|
||||
|
||||
Retrieve and consider the comments on the PR, which may have come from GitHub Copilot or Cursor BugBot. Think like GitHub Copilot or Cursor BugBot.
|
||||
|
||||
Offer to optionally post a brief summary of the review to the PR, via the gh CLI tool.
|
||||
|
||||
## Tagged Go releases
|
||||
|
||||
If I ask you whether we are ready to release, this means a tagged Go release on the main branch. Go releases are git tagged with a version number.
|
||||
|
||||
Review the changes since the last release, i.e. the previous git tag. Ensure that the changes are complete and correct. Identify new features, bug fixes, and performance improvements.
|
||||
|
||||
Identify breaking changes, especially API changes.
|
||||
|
||||
Ensure good test coverage. Look for performance changes, especially performance regressions, by running benchmarks against the previous release.
|
||||
|
||||
Ensure that the documentation in READMEs and GoDocs are complete, correct and consistent.
|
||||
|
||||
## Comparisons to go-runewidth
|
||||
|
||||
We originally attempted to make this package compatible with go-runewidth.
|
||||
However, we found that there were too many differences in the handling of
|
||||
certain characters and properties.
|
||||
|
||||
We believe, preliminarily, that our choices are more correct and complete,
|
||||
by using more complete categories such as Unicode Cf (format) for zero-width
|
||||
and Mn (Nonspacing_Mark) for combining marks.
|
||||
129
vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md
generated
vendored
Normal file
129
vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
# Changelog
|
||||
|
||||
## [0.11.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.10.0...v0.11.0)
|
||||
|
||||
### Added
|
||||
- New `ControlSequences8Bit` option to treat 8-bit ECMA-48 (C1) escape sequences as zero-width. (#22)
|
||||
|
||||
### Changed
|
||||
- Upgraded uax29 dependency to v2.7.0 for 8-bit escape sequence support in the grapheme iterator.
|
||||
- Truncation now validates that preserved trailing escape sequences are zero-width, preventing edge cases where non-zero-width sequences could leak into output.
|
||||
|
||||
### Note
|
||||
- `ControlSequences8Bit` is deliberately ignored by `TruncateString` and `TruncateBytes`, because C1 byte values (0x80–0x9F) overlap with UTF-8 multi-byte encoding.
|
||||
|
||||
## [0.10.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.9.0...v0.10.0)
|
||||
|
||||
### Added
|
||||
- New `ControlSequences` option to treat ECMA-48/ANSI escape sequences as zero-width. (#20)
|
||||
- `TruncateString` and `TruncateBytes` now preserve trailing ANSI escape sequences (such as SGR resets) when `ControlSequences` is true, preventing color bleed in terminal output.
|
||||
|
||||
### Changed
|
||||
- Removed `stringish` dependency; generic type constraints are now inline `~string | []byte`.
|
||||
- Upgraded uax29 dependency to v2.6.0 for ANSI escape sequence support in the grapheme iterator.
|
||||
|
||||
## [0.9.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.8.0...v0.9.0)
|
||||
|
||||
### Changed
|
||||
- Unicode 17 support: East Asian Width and emoji data updated to Unicode 17.0.0. (#18)
|
||||
- Upgraded uax29 dependency to v2.5.0 (Unicode 17 grapheme segmentation).
|
||||
|
||||
## [0.8.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.7.0...v0.8.0)
|
||||
|
||||
### Changed
|
||||
- Performance: ASCII fast path that applies to any run of printable
|
||||
ASCII. 2x-10x faster for ASCII text vs v0.7.0. (#16)
|
||||
- Upgraded uax29 dependency to v2.4.0 for Unicode 16 support. Text that includes
|
||||
Indic_Conjunct_Break may segment differently (and more correctly). (#15)
|
||||
|
||||
## [0.7.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.6.2...v0.7.0)
|
||||
|
||||
### Added
|
||||
- New `TruncateString` and `TruncateBytes` methods to truncate strings to a
|
||||
maximum display width, with optional tail (like an ellipsis). (#13)
|
||||
|
||||
## [0.6.2]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.6.1...v0.6.2)
|
||||
|
||||
### Changed
|
||||
- Internal: reduced property categories for simpler trie.
|
||||
|
||||
## [0.6.1]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.6.0...v0.6.1)
|
||||
|
||||
### Changed
|
||||
- Perf improvements: replaced the ASCII lookup table with a simple
|
||||
function. A bit more cache-friendly. More inlining.
|
||||
- Bug fix: single regional indicators are now treated as width 2, since that
|
||||
is what actual terminals do.
|
||||
|
||||
## [0.6.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.5.0...v0.6.0)
|
||||
|
||||
### Added
|
||||
- New `StringGraphemes` and `BytesGraphemes` methods, for iterating over the
|
||||
widths of grapheme clusters.
|
||||
|
||||
### Changed
|
||||
- Fast ASCII lookups
|
||||
|
||||
## [0.5.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.4.1...v0.5.0)
|
||||
|
||||
### Added
|
||||
- Unicode 16 support
|
||||
- Improved emoji presentation handling per Unicode TR51
|
||||
|
||||
### Changed
|
||||
- Corrected VS15 (U+FE0E) handling: now preserves base character width (no-op) per Unicode TR51
|
||||
- Performance optimizations: reduced property lookups
|
||||
|
||||
### Fixed
|
||||
- VS15 variation selector now correctly preserves base character width instead of forcing width 1
|
||||
|
||||
## [0.4.1]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.4.0...v0.4.1)
|
||||
|
||||
### Changed
|
||||
- Updated uax29 dependency
|
||||
- Improved flag handling
|
||||
|
||||
## [0.4.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.3.1...v0.4.0)
|
||||
|
||||
### Added
|
||||
- Support for variation selectors (VS15, VS16) and regional indicator pairs (flags)
|
||||
|
||||
## [0.3.1]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.3.0...v0.3.1)
|
||||
|
||||
### Added
|
||||
- Fuzz testing support
|
||||
|
||||
### Changed
|
||||
- Updated stringish dependency
|
||||
|
||||
## [0.3.0]
|
||||
|
||||
[Compare](https://github.com/clipperhouse/displaywidth/compare/v0.2.0...v0.3.0)
|
||||
|
||||
### Changed
|
||||
- Dropped compatibility with go-runewidth
|
||||
- Trie implementation cleanup
|
||||
21
vendor/github.com/clipperhouse/displaywidth/LICENSE
generated
vendored
Normal file
21
vendor/github.com/clipperhouse/displaywidth/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Matt Sherman
|
||||
|
||||
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.
|
||||
190
vendor/github.com/clipperhouse/displaywidth/README.md
generated
vendored
Normal file
190
vendor/github.com/clipperhouse/displaywidth/README.md
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
# displaywidth
|
||||
|
||||
A high-performance Go package for measuring the monospace display width of strings, UTF-8 bytes, and runes.
|
||||
|
||||
[](https://pkg.go.dev/github.com/clipperhouse/displaywidth)
|
||||
[](https://github.com/clipperhouse/displaywidth/actions/workflows/gotest.yml)
|
||||
[](https://github.com/clipperhouse/displaywidth/actions/workflows/gofuzz.yml)
|
||||
|
||||
## Install
|
||||
```bash
|
||||
go get github.com/clipperhouse/displaywidth
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/clipperhouse/displaywidth"
|
||||
)
|
||||
|
||||
func main() {
|
||||
width := displaywidth.String("Hello, 世界!")
|
||||
fmt.Println(width)
|
||||
|
||||
width = displaywidth.Bytes([]byte("🌍"))
|
||||
fmt.Println(width)
|
||||
|
||||
width = displaywidth.Rune('🌍')
|
||||
fmt.Println(width)
|
||||
}
|
||||
```
|
||||
|
||||
For most purposes, you should use the `String` or `Bytes` methods. They sum
|
||||
the widths of grapheme clusters in the string or byte slice.
|
||||
|
||||
> Note: in your application, iterating over runes to measure width is likely incorrect;
|
||||
the smallest unit of display is a grapheme, not a rune.
|
||||
|
||||
### Iterating over graphemes
|
||||
|
||||
If you need the individual graphemes:
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/clipperhouse/displaywidth"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g := displaywidth.StringGraphemes("Hello, 世界!")
|
||||
for g.Next() {
|
||||
width := g.Width()
|
||||
value := g.Value()
|
||||
// do something with the width or value
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
Create the options you need, and then use methods on the options struct.
|
||||
|
||||
```go
|
||||
var myOptions = displaywidth.Options{
|
||||
EastAsianWidth: true,
|
||||
ControlSequences: true,
|
||||
}
|
||||
|
||||
width := myOptions.String("Hello, 世界!")
|
||||
```
|
||||
|
||||
#### ControlSequences
|
||||
|
||||
`ControlSequences` specifies whether to ignore ECMA-48 escape sequences
|
||||
when calculating the display width. When `false` (default), ANSI escape
|
||||
sequences are treated as just a series of characters. When `true`, they are
|
||||
treated as a single zero-width unit.
|
||||
|
||||
#### ControlSequences8Bit
|
||||
|
||||
`ControlSequences8Bit` specifies whether to ignore 8-bit ECMA-48 escape sequences
|
||||
when calculating the display width. When `false` (default), these are treated
|
||||
as just a series of characters. When `true`, they are treated as a single
|
||||
zero-width unit.
|
||||
|
||||
Note: this option is ignored by the `Truncate` methods, as the concatenation
|
||||
can lead to unintended UTF-8 semantics.
|
||||
|
||||
#### EastAsianWidth
|
||||
|
||||
`EastAsianWidth` defines how
|
||||
[East Asian Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous)
|
||||
are treated.
|
||||
|
||||
When `false` (default), East Asian Ambiguous characters are treated as width 1.
|
||||
When `true`, they are treated as width 2.
|
||||
|
||||
You may wish to configure this based on environment variables or locale.
|
||||
`go-runewidth`, for example, does so
|
||||
[during package initialization](https://github.com/mattn/go-runewidth/blob/master/runewidth.go#L26C1-L45C2). `displaywidth` does not do this automatically, we prefer to leave it to you.
|
||||
|
||||
|
||||
## Technical standards and compatibility
|
||||
|
||||
This package implements the Unicode East Asian Width standard
|
||||
([UAX #11](https://www.unicode.org/reports/tr11/tr11-43.html)), and handles
|
||||
[version selectors](https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block)),
|
||||
and [regional indicator pairs](https://en.wikipedia.org/wiki/Regional_indicator_symbol)
|
||||
(flags). We implement [Unicode TR51](https://www.unicode.org/reports/tr51/tr51-27.html)
|
||||
for emojis. We are keeping an eye on
|
||||
[emerging standards](https://www.jeffquast.com/post/state-of-terminal-emulation-2025/).
|
||||
|
||||
For control sequences, we implement the [ECMA-48](https://ecma-international.org/publications-and-standards/standards/ecma-48/) standard for 7-bit and 8-bit control sequences.
|
||||
|
||||
`clipperhouse/displaywidth`, `mattn/go-runewidth`, and `rivo/uniseg` will
|
||||
give the same outputs for most real-world text. Extensive details are in the
|
||||
[compatibility analysis](comparison/COMPATIBILITY_ANALYSIS.md).
|
||||
|
||||
## Invalid UTF-8
|
||||
|
||||
This package does not validate UTF-8. If you pass invalid UTF-8, the results
|
||||
are undefined. We fuzz against invalid UTF-8 to ensure we don't panic or
|
||||
loop indefinitely.
|
||||
|
||||
The `ControlSequences8Bit` option means that we will segment valid 8-bit
|
||||
control sequences, which are typically _not_ valid UTF-8. 8-bit control bytes
|
||||
happen to also be UTF-8 continuation bytes. Use with caution.
|
||||
|
||||
## Prior Art
|
||||
|
||||
[mattn/go-runewidth](https://github.com/mattn/go-runewidth)
|
||||
|
||||
[rivo/uniseg](https://github.com/rivo/uniseg)
|
||||
|
||||
[x/text/width](https://pkg.go.dev/golang.org/x/text/width)
|
||||
|
||||
[x/text/internal/triegen](https://pkg.go.dev/golang.org/x/text/internal/triegen)
|
||||
|
||||
## Benchmarks
|
||||
|
||||
```bash
|
||||
cd comparison
|
||||
go test -bench=. -benchmem
|
||||
```
|
||||
|
||||
```
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: github.com/clipperhouse/displaywidth/comparison
|
||||
cpu: Apple M2
|
||||
|
||||
BenchmarkString_Mixed/clipperhouse/displaywidth-8 5784 ns/op 291.69 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_Mixed/mattn/go-runewidth-8 14751 ns/op 114.36 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_Mixed/rivo/uniseg-8 19360 ns/op 87.14 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkString_ASCII/clipperhouse/displaywidth-8 54.60 ns/op 2344.32 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_ASCII/mattn/go-runewidth-8 1195 ns/op 107.08 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_ASCII/rivo/uniseg-8 1578 ns/op 81.13 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkString_EastAsian/clipperhouse/displaywidth-8 5837 ns/op 289.01 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_EastAsian/mattn/go-runewidth-8 24418 ns/op 69.09 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_EastAsian/rivo/uniseg-8 19339 ns/op 87.23 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkString_Emoji/clipperhouse/displaywidth-8 3225 ns/op 224.51 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_Emoji/mattn/go-runewidth-8 4851 ns/op 149.25 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkString_Emoji/rivo/uniseg-8 6591 ns/op 109.85 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkRune_Mixed/clipperhouse/displaywidth-8 3385 ns/op 498.34 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkRune_Mixed/mattn/go-runewidth-8 5354 ns/op 315.07 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkRune_EastAsian/clipperhouse/displaywidth-8 3397 ns/op 496.56 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkRune_EastAsian/mattn/go-runewidth-8 15673 ns/op 107.64 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkRune_ASCII/clipperhouse/displaywidth-8 255.7 ns/op 500.53 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkRune_ASCII/mattn/go-runewidth-8 261.5 ns/op 489.55 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkRune_Emoji/clipperhouse/displaywidth-8 1371 ns/op 528.22 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkRune_Emoji/mattn/go-runewidth-8 2267 ns/op 319.43 MB/s 0 B/op 0 allocs/op
|
||||
|
||||
BenchmarkTruncateWithTail/clipperhouse/displaywidth-8 3229 ns/op 54.82 MB/s 192 B/op 14 allocs/op
|
||||
BenchmarkTruncateWithTail/mattn/go-runewidth-8 8408 ns/op 21.05 MB/s 192 B/op 14 allocs/op
|
||||
|
||||
BenchmarkTruncateWithoutTail/clipperhouse/displaywidth-8 3554 ns/op 64.43 MB/s 0 B/op 0 allocs/op
|
||||
BenchmarkTruncateWithoutTail/mattn/go-runewidth-8 11189 ns/op 20.47 MB/s 0 B/op 0 allocs/op
|
||||
```
|
||||
|
||||
Here are some notes on [how to make Unicode things fast](https://clipperhouse.com/go-unicode/).
|
||||
3
vendor/github.com/clipperhouse/displaywidth/gen.go
generated
vendored
Normal file
3
vendor/github.com/clipperhouse/displaywidth/gen.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package displaywidth
|
||||
|
||||
//go:generate go run -C internal/gen .
|
||||
73
vendor/github.com/clipperhouse/displaywidth/graphemes.go
generated
vendored
Normal file
73
vendor/github.com/clipperhouse/displaywidth/graphemes.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
package displaywidth
|
||||
|
||||
import (
|
||||
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||
)
|
||||
|
||||
// Graphemes is an iterator over grapheme clusters.
|
||||
//
|
||||
// Iterate using the Next method, and get the width of the current grapheme
|
||||
// using the Width method.
|
||||
type Graphemes[T ~string | []byte] struct {
|
||||
iter *graphemes.Iterator[T]
|
||||
options Options
|
||||
}
|
||||
|
||||
// Next advances the iterator to the next grapheme cluster.
|
||||
func (g *Graphemes[T]) Next() bool {
|
||||
return g.iter.Next()
|
||||
}
|
||||
|
||||
// Value returns the current grapheme cluster.
|
||||
func (g *Graphemes[T]) Value() T {
|
||||
return g.iter.Value()
|
||||
}
|
||||
|
||||
// Width returns the display width of the current grapheme cluster.
|
||||
func (g *Graphemes[T]) Width() int {
|
||||
return graphemeWidth(g.Value(), g.options)
|
||||
}
|
||||
|
||||
// StringGraphemes returns an iterator over grapheme clusters for the given
|
||||
// string.
|
||||
//
|
||||
// Iterate using the Next method, and get the width of the current grapheme
|
||||
// using the Width method.
|
||||
func StringGraphemes(s string) Graphemes[string] {
|
||||
return DefaultOptions.StringGraphemes(s)
|
||||
}
|
||||
|
||||
// StringGraphemes returns an iterator over grapheme clusters for the given
|
||||
// string, with the given options.
|
||||
//
|
||||
// Iterate using the Next method, and get the width of the current grapheme
|
||||
// using the Width method.
|
||||
func (options Options) StringGraphemes(s string) Graphemes[string] {
|
||||
g := graphemes.FromString(s)
|
||||
g.AnsiEscapeSequences = options.ControlSequences
|
||||
g.AnsiEscapeSequences8Bit = options.ControlSequences8Bit
|
||||
|
||||
return Graphemes[string]{iter: g, options: options}
|
||||
}
|
||||
|
||||
// BytesGraphemes returns an iterator over grapheme clusters for the given
|
||||
// []byte.
|
||||
//
|
||||
// Iterate using the Next method, and get the width of the current grapheme
|
||||
// using the Width method.
|
||||
func BytesGraphemes(s []byte) Graphemes[[]byte] {
|
||||
return DefaultOptions.BytesGraphemes(s)
|
||||
}
|
||||
|
||||
// BytesGraphemes returns an iterator over grapheme clusters for the given
|
||||
// []byte, with the given options.
|
||||
//
|
||||
// Iterate using the Next method, and get the width of the current grapheme
|
||||
// using the Width method.
|
||||
func (options Options) BytesGraphemes(s []byte) Graphemes[[]byte] {
|
||||
g := graphemes.FromBytes(s)
|
||||
g.AnsiEscapeSequences = options.ControlSequences
|
||||
g.AnsiEscapeSequences8Bit = options.ControlSequences8Bit
|
||||
|
||||
return Graphemes[[]byte]{iter: g, options: options}
|
||||
}
|
||||
30
vendor/github.com/clipperhouse/displaywidth/options.go
generated
vendored
Normal file
30
vendor/github.com/clipperhouse/displaywidth/options.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package displaywidth
|
||||
|
||||
// Options allows you to specify the treatment of ambiguous East Asian
|
||||
// characters and ANSI escape sequences.
|
||||
type Options struct {
|
||||
// EastAsianWidth specifies whether to treat ambiguous East Asian characters
|
||||
// as width 1 or 2. When false (default), ambiguous East Asian characters
|
||||
// are treated as width 1. When true, they are width 2.
|
||||
EastAsianWidth bool
|
||||
|
||||
// ControlSequences specifies whether to ignore 7-bit ECMA-48 escape sequences
|
||||
// when calculating the display width. When false (default), ANSI escape
|
||||
// sequences are treated as just a series of characters. When true, they are
|
||||
// treated as a single zero-width unit.
|
||||
ControlSequences bool
|
||||
// ControlSequences8Bit specifies whether to ignore 8-bit ECMA-48 escape sequences
|
||||
// when calculating the display width. When false (default), these are treated
|
||||
// as just a series of characters. When true, they are treated as a single
|
||||
// zero-width unit.
|
||||
ControlSequences8Bit bool
|
||||
}
|
||||
|
||||
// DefaultOptions is the default options for the display width
|
||||
// calculation, which is EastAsianWidth false, ControlSequences false, and
|
||||
// ControlSequences8Bit false.
|
||||
var DefaultOptions = Options{
|
||||
EastAsianWidth: false,
|
||||
ControlSequences: false,
|
||||
ControlSequences8Bit: false,
|
||||
}
|
||||
1699
vendor/github.com/clipperhouse/displaywidth/trie.go
generated
vendored
Normal file
1699
vendor/github.com/clipperhouse/displaywidth/trie.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
149
vendor/github.com/clipperhouse/displaywidth/truncate.go
generated
vendored
Normal file
149
vendor/github.com/clipperhouse/displaywidth/truncate.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package displaywidth
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||
)
|
||||
|
||||
// TruncateString truncates a string to the given maxWidth, and appends the
|
||||
// given tail if the string is truncated.
|
||||
//
|
||||
// It ensures the visible width, including the width of the tail, is less than or
|
||||
// equal to maxWidth.
|
||||
//
|
||||
// When [Options.ControlSequences] is true, 7-bit ANSI escape sequences that
|
||||
// appear after the truncation point are preserved in the output. This ensures
|
||||
// that escape sequences such as SGR resets are not lost, preventing color
|
||||
// bleed in terminal output.
|
||||
//
|
||||
// [Options.ControlSequences8Bit] is ignored by truncation. 8-bit C1 byte values
|
||||
// (0x80-0x9F) overlap with UTF-8 multi-byte encoding, so manipulating them
|
||||
// during truncation can shift byte boundaries and form unintended visible
|
||||
// characters. Use [Options.String] or [Options.Bytes] for 8-bit-aware width
|
||||
// measurement.
|
||||
func (options Options) TruncateString(s string, maxWidth int, tail string) string {
|
||||
// We deliberately ignore ControlSequences8Bit for truncation, see above.
|
||||
options.ControlSequences8Bit = false
|
||||
|
||||
maxWidthWithoutTail := maxWidth - options.String(tail)
|
||||
|
||||
var pos, total int
|
||||
g := graphemes.FromString(s)
|
||||
g.AnsiEscapeSequences = options.ControlSequences
|
||||
|
||||
for g.Next() {
|
||||
gw := graphemeWidth(g.Value(), options)
|
||||
if total+gw <= maxWidthWithoutTail {
|
||||
pos = g.End()
|
||||
}
|
||||
total += gw
|
||||
if total > maxWidth {
|
||||
if options.ControlSequences {
|
||||
// Build result with trailing 7-bit ANSI escape sequences preserved
|
||||
var b strings.Builder
|
||||
b.Grow(len(s) + len(tail)) // at most original + tail
|
||||
b.WriteString(s[:pos])
|
||||
b.WriteString(tail)
|
||||
|
||||
rem := graphemes.FromString(s[pos:])
|
||||
rem.AnsiEscapeSequences = options.ControlSequences
|
||||
|
||||
for rem.Next() {
|
||||
v := rem.Value()
|
||||
// Only preserve 7-bit escapes (ESC = 0x1B) that measure
|
||||
// as zero-width on their own; some sequences (e.g. SOS)
|
||||
// are only valid in their original context.
|
||||
if len(v) > 0 && v[0] == 0x1B && options.String(v) == 0 {
|
||||
b.WriteString(v)
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
return s[:pos] + tail
|
||||
}
|
||||
}
|
||||
// No truncation
|
||||
return s
|
||||
}
|
||||
|
||||
// TruncateString truncates a string to the given maxWidth, and appends the
|
||||
// given tail if the string is truncated.
|
||||
//
|
||||
// It ensures the total width, including the width of the tail, is less than or
|
||||
// equal to maxWidth.
|
||||
func TruncateString(s string, maxWidth int, tail string) string {
|
||||
return DefaultOptions.TruncateString(s, maxWidth, tail)
|
||||
}
|
||||
|
||||
// TruncateBytes truncates a []byte to the given maxWidth, and appends the
|
||||
// given tail if the []byte is truncated.
|
||||
//
|
||||
// It ensures the visible width, including the width of the tail, is less than or
|
||||
// equal to maxWidth.
|
||||
//
|
||||
// When [Options.ControlSequences] is true, 7-bit ANSI escape sequences that
|
||||
// appear after the truncation point are preserved in the output. This ensures
|
||||
// that escape sequences such as SGR resets are not lost, preventing color
|
||||
// bleed in terminal output.
|
||||
//
|
||||
// [Options.ControlSequences8Bit] is ignored by truncation. 8-bit C1 byte values
|
||||
// (0x80-0x9F) overlap with UTF-8 multi-byte encoding, so manipulating them
|
||||
// during truncation can shift byte boundaries and form unintended visible
|
||||
// characters. Use [Options.String] or [Options.Bytes] for 8-bit-aware width
|
||||
// measurement.
|
||||
func (options Options) TruncateBytes(s []byte, maxWidth int, tail []byte) []byte {
|
||||
// We deliberately ignore ControlSequences8Bit for truncation, see above.
|
||||
options.ControlSequences8Bit = false
|
||||
|
||||
maxWidthWithoutTail := maxWidth - options.Bytes(tail)
|
||||
|
||||
var pos, total int
|
||||
g := graphemes.FromBytes(s)
|
||||
g.AnsiEscapeSequences = options.ControlSequences
|
||||
|
||||
for g.Next() {
|
||||
gw := graphemeWidth(g.Value(), options)
|
||||
if total+gw <= maxWidthWithoutTail {
|
||||
pos = g.End()
|
||||
}
|
||||
total += gw
|
||||
if total > maxWidth {
|
||||
if options.ControlSequences {
|
||||
// Build result with trailing 7-bit ANSI escape sequences preserved
|
||||
result := make([]byte, 0, len(s)+len(tail)) // at most original + tail
|
||||
result = append(result, s[:pos]...)
|
||||
result = append(result, tail...)
|
||||
|
||||
rem := graphemes.FromBytes(s[pos:])
|
||||
rem.AnsiEscapeSequences = options.ControlSequences
|
||||
|
||||
for rem.Next() {
|
||||
v := rem.Value()
|
||||
// Only preserve 7-bit escapes (ESC = 0x1B) that measure
|
||||
// as zero-width on their own; some sequences (e.g. SOS)
|
||||
// are only valid in their original context.
|
||||
if len(v) > 0 && v[0] == 0x1B && options.Bytes(v) == 0 {
|
||||
result = append(result, v...)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
result := make([]byte, 0, pos+len(tail))
|
||||
result = append(result, s[:pos]...)
|
||||
result = append(result, tail...)
|
||||
return result
|
||||
}
|
||||
}
|
||||
// No truncation
|
||||
return s
|
||||
}
|
||||
|
||||
// TruncateBytes truncates a []byte to the given maxWidth, and appends the
|
||||
// given tail if the []byte is truncated.
|
||||
//
|
||||
// It ensures the total width, including the width of the tail, is less than or
|
||||
// equal to maxWidth.
|
||||
func TruncateBytes(s []byte, maxWidth int, tail []byte) []byte {
|
||||
return DefaultOptions.TruncateBytes(s, maxWidth, tail)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user