Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
45af67d22d
|
|||
|
db7c4042d0
|
|||
|
ed1a66dc5f
|
|||
|
bb93e4266a
|
|||
|
a2cc70b2f5
|
|||
|
ce1aa3d870
|
|||
|
d75700c8a9
|
|||
|
0ccc4aae72
|
|||
|
ec22d5d51d
|
|||
|
ab42584d05
|
|||
| 40eb6e9a18 | |||
| 35eb9d4a89 | |||
|
08cc63d523
|
|||
| 797b8d899b | |||
|
fb786306b5
|
|||
| c3a2048eba | |||
| 1bdc11ba62 | |||
| cc8703310c | |||
|
fcd5bd863d
|
|||
|
e6af2da9dd
|
|||
| 4b688825e0 |
@ -260,6 +260,7 @@ checkout as-is. Recipe commit hashes are also supported as values for
|
|||||||
app.Name,
|
app.Name,
|
||||||
app.Server,
|
app.Server,
|
||||||
internal.DontWaitConverge,
|
internal.DontWaitConverge,
|
||||||
|
internal.NoInput,
|
||||||
f,
|
f,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|||||||
@ -128,6 +128,7 @@ Pass "--all-services/-a" to restart all services.`),
|
|||||||
AppName: app.Name,
|
AppName: app.Name,
|
||||||
ServerName: app.Server,
|
ServerName: app.Server,
|
||||||
Filters: f,
|
Filters: f,
|
||||||
|
NoInput: internal.NoInput,
|
||||||
NoLog: true,
|
NoLog: true,
|
||||||
Quiet: true,
|
Quiet: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -246,6 +246,7 @@ beforehand. See "abra app backup" for more.`),
|
|||||||
stackName,
|
stackName,
|
||||||
app.Server,
|
app.Server,
|
||||||
internal.DontWaitConverge,
|
internal.DontWaitConverge,
|
||||||
|
internal.NoInput,
|
||||||
f,
|
f,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|||||||
@ -282,6 +282,7 @@ beforehand. See "abra app backup" for more.`),
|
|||||||
stackName,
|
stackName,
|
||||||
app.Server,
|
app.Server,
|
||||||
internal.DontWaitConverge,
|
internal.DontWaitConverge,
|
||||||
|
internal.NoInput,
|
||||||
f,
|
f,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|||||||
@ -64,7 +64,7 @@ func DeployOverview(
|
|||||||
server = "local"
|
server = "local"
|
||||||
}
|
}
|
||||||
|
|
||||||
domain := app.Domain
|
domain := fmt.Sprintf("https://%s", app.Domain)
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
domain = config.MISSING_DEFAULT
|
domain = config.MISSING_DEFAULT
|
||||||
}
|
}
|
||||||
|
|||||||
69
go.mod
69
go.mod
@ -1,30 +1,26 @@
|
|||||||
module coopcloud.tech/abra
|
module coopcloud.tech/abra
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.2
|
||||||
|
|
||||||
toolchain go1.24.1
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca
|
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca
|
||||||
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||||
github.com/charmbracelet/bubbles v0.21.0
|
|
||||||
github.com/charmbracelet/bubbletea v1.3.10
|
github.com/charmbracelet/bubbletea v1.3.10
|
||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
github.com/charmbracelet/log v0.4.2
|
github.com/charmbracelet/log v0.4.2
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli v28.4.0+incompatible
|
github.com/docker/cli v29.0.0+incompatible
|
||||||
github.com/docker/docker v28.4.0+incompatible
|
github.com/docker/docker v28.5.2+incompatible
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/evertras/bubble-table v0.19.2
|
github.com/go-git/go-git/v5 v5.16.3
|
||||||
github.com/go-git/go-git/v5 v5.16.2
|
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/leonelquinteros/gotext v1.7.2
|
github.com/leonelquinteros/gotext v1.7.2
|
||||||
github.com/moby/sys/signal v0.7.1
|
github.com/moby/sys/signal v0.7.1
|
||||||
github.com/moby/term v0.5.2
|
github.com/moby/term v0.5.2
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/schollz/progressbar/v3 v3.18.0
|
github.com/schollz/progressbar/v3 v3.18.0
|
||||||
golang.org/x/term v0.35.0
|
golang.org/x/term v0.36.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gotest.tools/v3 v3.5.2
|
gotest.tools/v3 v3.5.2
|
||||||
)
|
)
|
||||||
@ -35,24 +31,26 @@ require (
|
|||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // 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.3.0 // indirect
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.3.2 // indirect
|
github.com/charmbracelet/colorprofile v0.3.3 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.10.2 // indirect
|
github.com/charmbracelet/x/ansi v0.11.0 // indirect
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 // indirect
|
||||||
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
|
github.com/clipperhouse/displaywidth v0.5.0 // indirect
|
||||||
|
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/cloudflare/circl v1.6.1 // indirect
|
||||||
github.com/containerd/errdefs v1.0.0 // indirect
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/platforms v0.2.1 // indirect
|
github.com/containerd/platforms v0.2.1 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // 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.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
github.com/docker/go-connections v0.6.0 // indirect
|
github.com/docker/go-connections v0.6.0 // indirect
|
||||||
@ -64,19 +62,19 @@ require (
|
|||||||
github.com/ghodss/yaml v1.0.0 // 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/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // 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.4.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/google/uuid v1.6.0 // 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.27.3 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // 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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.1 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // 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.3.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
@ -88,13 +86,14 @@ require (
|
|||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/go-archive v0.1.0 // indirect
|
github.com/moby/go-archive v0.1.0 // indirect
|
||||||
|
github.com/moby/moby/api v1.52.0 // indirect
|
||||||
|
github.com/moby/moby/client v0.1.0 // indirect
|
||||||
github.com/moby/sys/atomicwriter v0.1.0 // indirect
|
github.com/moby/sys/atomicwriter v0.1.0 // indirect
|
||||||
github.com/moby/sys/user v0.4.0 // indirect
|
github.com/moby/sys/user v0.4.0 // indirect
|
||||||
github.com/moby/sys/userns v0.1.0 // indirect
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/muesli/reflow v0.3.0 // indirect
|
|
||||||
github.com/muesli/termenv v0.16.0 // indirect
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
@ -103,12 +102,12 @@ require (
|
|||||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.66.1 // indirect
|
github.com/prometheus/common v0.67.2 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.19.2 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.10 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
@ -125,17 +124,17 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk 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/sdk/metric v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.8.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.42.0 // indirect
|
golang.org/x/crypto v0.43.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||||
golang.org/x/net v0.44.0 // indirect
|
golang.org/x/net v0.46.0 // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
golang.org/x/time v0.13.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20251110190251-83f479183930 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251110190251-83f479183930 // indirect
|
||||||
google.golang.org/grpc v1.75.1 // indirect
|
google.golang.org/grpc v1.76.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
@ -144,7 +143,7 @@ require (
|
|||||||
github.com/containers/image v3.0.2+incompatible
|
github.com/containers/image v3.0.2+incompatible
|
||||||
github.com/containers/storage v1.38.2 // indirect
|
github.com/containers/storage v1.38.2 // indirect
|
||||||
github.com/decentral1se/passgen v1.0.1
|
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.4 // indirect
|
||||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
@ -158,5 +157,5 @@ require (
|
|||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/theupdateframework/notary v0.7.0 // indirect
|
github.com/theupdateframework/notary v0.7.0 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
golang.org/x/sys v0.36.0
|
golang.org/x/sys v0.38.0
|
||||||
)
|
)
|
||||||
|
|||||||
80
go.sum
80
go.sum
@ -99,8 +99,6 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
|
|||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
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/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=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
|
||||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
|
||||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
@ -131,28 +129,35 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
|
|||||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
|
||||||
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
|
||||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
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 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
|
||||||
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
|
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
|
||||||
|
github.com/charmbracelet/colorprofile v0.3.3 h1:DjJzJtLP6/NZ8p7Cgjno0CKGr7wwRJGxWUwh2IyhfAI=
|
||||||
|
github.com/charmbracelet/colorprofile v0.3.3/go.mod h1:nB1FugsAbzq284eJcjfah2nhdSLppN2NqvfotkfRYP4=
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
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/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 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
||||||
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
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 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
|
||||||
github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
|
github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.0 h1:uuIVK7GIplwX6UBIz8S2TF8nkr7xRlygSsBRjSJqIvA=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.0/go.mod h1:uQt8bOrq/xgXjlGcFMc8U2WYbnxyjrKhnvTQluvfCaE=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
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/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
|
||||||
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 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
||||||
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
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 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
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/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.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||||
@ -168,8 +173,14 @@ 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.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/clipperhouse/displaywidth v0.5.0 h1:AIG5vQaSL2EKqzt0M9JMnvNxOCRTKUc4vUnLWGgP89I=
|
||||||
|
github.com/clipperhouse/displaywidth v0.5.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||||
|
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||||
|
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||||
github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
|
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/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
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 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
@ -304,6 +315,8 @@ github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2
|
|||||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
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 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw=
|
||||||
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
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/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||||
@ -324,6 +337,8 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG
|
|||||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY=
|
github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY=
|
||||||
github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
|
github.com/docker/cli v29.0.0+incompatible h1:KgsN2RUFMNM8wChxryicn4p46BdQWpXOA1XLGBGPGAw=
|
||||||
|
github.com/docker/cli v29.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
@ -332,9 +347,13 @@ github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc
|
|||||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
|
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
|
||||||
github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
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.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 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.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||||
|
github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI=
|
||||||
|
github.com/docker/docker-credential-helpers v0.9.4/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 h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
|
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=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
@ -373,8 +392,6 @@ github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6
|
|||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evertras/bubble-table v0.19.2 h1:u77oiM6JlRR+CvS5FZc3Hz+J6iEsvEDcR5kO8OFb1Yw=
|
|
||||||
github.com/evertras/bubble-table v0.19.2/go.mod h1:ifHujS1YxwnYSOgcR2+m3GnJ84f7CVU/4kUOxUCjEbQ=
|
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
@ -401,6 +418,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj
|
|||||||
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-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 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.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
||||||
|
github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8=
|
||||||
|
github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
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-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@ -411,6 +430,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
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 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
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.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 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=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
@ -535,9 +556,12 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de
|
|||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
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.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.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
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 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.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
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 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=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
@ -597,6 +621,8 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
|
|||||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
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 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.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||||
|
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
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/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
@ -640,7 +666,6 @@ 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 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
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.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
|
||||||
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
|
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.19/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.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||||
@ -669,6 +694,10 @@ 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 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||||
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
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/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
|
github.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg=
|
||||||
|
github.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
|
||||||
|
github.com/moby/moby/client v0.1.0 h1:nt+hn6O9cyJQqq5UWnFGqsZRTS/JirUqzPjEl0Bdc/8=
|
||||||
|
github.com/moby/moby/client v0.1.0/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=
|
||||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
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.0/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 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||||
@ -702,8 +731,6 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D
|
|||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
|
||||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
|
||||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
@ -804,6 +831,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
|
|||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
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 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||||
|
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||||
|
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
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-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-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
@ -817,9 +846,9 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
|||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
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 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||||
|
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||||
|
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
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=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
@ -827,6 +856,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
|||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@ -852,6 +883,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
|||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
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 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||||
|
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/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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
@ -975,6 +1008,8 @@ go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42s
|
|||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
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 h1:fRAZQDcAFHySxpJ1TwlA1cJ4tvcrw7nXl9xWWC8N5CE=
|
||||||
go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0=
|
go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
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/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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
@ -1003,6 +1038,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
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 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||||
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -1015,6 +1052,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
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 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-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||||
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||||
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
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/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=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -1080,6 +1119,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
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 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||||
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1177,11 +1218,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.6.0/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 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
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-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.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 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||||
|
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||||
|
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1193,6 +1238,8 @@ 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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
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.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||||
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
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-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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -1201,6 +1248,8 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/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 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
||||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
|
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -1298,8 +1347,12 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc
|
|||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
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 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/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20251110190251-83f479183930 h1:8BWFtrvJRbplrKV5VHlIm4YM726eeBPPAL2QDNWhRrU=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20251110190251-83f479183930/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4=
|
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/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251110190251-83f479183930 h1:tK4fkUnnRhig9TsTp4otV1FxwBFYgbKUq1RY0V6KZ4U=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251110190251-83f479183930/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
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.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@ -1321,6 +1374,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
|
|||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
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 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
||||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||||
|
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||||
|
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@ -1336,6 +1391,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.27.1/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 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
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/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=
|
gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=
|
||||||
@ -1373,6 +1430,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
|
|||||||
@ -633,6 +633,11 @@ func (a App) WipeRecipeVersion() error {
|
|||||||
|
|
||||||
// WriteRecipeVersion writes the recipe version to the app .env file.
|
// WriteRecipeVersion writes the recipe version to the app .env file.
|
||||||
func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
||||||
|
if version == config.UNKNOWN_DEFAULT {
|
||||||
|
log.Debug(i18n.G("version is unknown, skipping env write"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
file, err := os.Open(a.Path)
|
file, err := os.Open(a.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -224,3 +224,16 @@ func TestWriteRecipeVersionOverwrite(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, "foo", app.Recipe.EnvVersion)
|
assert.Equal(t, "foo", app.Recipe.EnvVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteRecipeVersionUnknown(t *testing.T) {
|
||||||
|
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.WriteRecipeVersion(config.UNKNOWN_DEFAULT, false); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NotEqual(t, config.UNKNOWN_DEFAULT, app.Recipe.EnvVersion)
|
||||||
|
}
|
||||||
|
|||||||
@ -37,18 +37,27 @@ func WithTimeout(timeout int) Opt {
|
|||||||
// New initiates a new Docker client. New client connections are validated so
|
// New initiates a new Docker client. New client connections are validated so
|
||||||
// that we ensure connections via SSH to the daemon can succeed. It takes into
|
// that we ensure connections via SSH to the daemon can succeed. It takes into
|
||||||
// account that you may only want the local client and not communicate via SSH.
|
// account that you may only want the local client and not communicate via SSH.
|
||||||
// For this use-case, please pass "default" as the contextName.
|
// For this use-case, please pass "default" as the serverName.
|
||||||
func New(serverName string, opts ...Opt) (*client.Client, error) {
|
func New(serverName string, opts ...Opt) (*client.Client, error) {
|
||||||
var clientOpts []client.Opt
|
var clientOpts []client.Opt
|
||||||
|
|
||||||
ctx, err := GetContext(serverName)
|
ctx, err := GetContext(serverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serverDir := path.Join(config.SERVERS_DIR, serverName)
|
serverDir := path.Join(config.SERVERS_DIR, serverName)
|
||||||
if _, err := os.Stat(serverDir); err == nil {
|
if _, err := os.Stat(serverDir); err != nil {
|
||||||
return nil, errors.New(i18n.G("server missing context, run \"abra server add %s\"?", serverName))
|
return nil, errors.New(i18n.G("server missing, run \"abra server add %s\"?", serverName))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New(i18n.G("unknown server, run \"abra server add %s\"?", serverName))
|
// NOTE(p4u1): when the docker context does not exist but the server folder
|
||||||
|
// is there, let's create a new docker context.
|
||||||
|
if err = CreateContext(serverName); err != nil {
|
||||||
|
return nil, errors.New(i18n.G("server missing context, context creation failed: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err = GetContext(serverName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New(i18n.G("server missing context, run \"abra server add %s\"?", serverName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxEndpoint, err := contextPkg.GetContextEndpoint(ctx)
|
ctxEndpoint, err := contextPkg.GetContextEndpoint(ctx)
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Project-Id-Version: \n"
|
msgstr "Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||||
"POT-Creation-Date: 2025-11-02 11:41+0100\n"
|
"POT-Creation-Date: 2025-11-04 15:34+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -274,12 +274,12 @@ msgstr ""
|
|||||||
msgid "%s has been detected as not deployed"
|
msgid "%s has been detected as not deployed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:139
|
#: ./cli/app/restart.go:140
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s has been scaled to 0"
|
msgid "%s has been scaled to 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:150
|
#: ./cli/app/restart.go:151
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s has been scaled to 1"
|
msgid "%s has been scaled to 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -339,17 +339,17 @@ msgstr ""
|
|||||||
msgid "%s is missing the TYPE env var?"
|
msgid "%s is missing the TYPE env var?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/rollback.go:308 ./cli/app/rollback.go:312
|
#: ./cli/app/rollback.go:309 ./cli/app/rollback.go:313
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not a downgrade for %s?"
|
msgid "%s is not a downgrade for %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:428 ./cli/app/upgrade.go:432
|
#: ./cli/app/upgrade.go:429 ./cli/app/upgrade.go:433
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not an upgrade for %s?"
|
msgid "%s is not an upgrade for %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/env.go:146 ./cli/app/logs.go:65 ./cli/app/ps.go:62 ./cli/app/restart.go:100 ./cli/app/services.go:55 ./cli/app/undeploy.go:66 ./cli/app/upgrade.go:449
|
#: ./cli/app/env.go:146 ./cli/app/logs.go:65 ./cli/app/ps.go:62 ./cli/app/restart.go:100 ./cli/app/services.go:55 ./cli/app/undeploy.go:66 ./cli/app/upgrade.go:450
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not deployed?"
|
msgid "%s is not deployed?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -424,7 +424,7 @@ msgstr ""
|
|||||||
msgid "%s service is missing image tag?"
|
msgid "%s service is missing image tag?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:151
|
#: ./cli/app/restart.go:152
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s service successfully restarted"
|
msgid "%s service successfully restarted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -459,7 +459,7 @@ msgstr ""
|
|||||||
msgid "%s/example.git"
|
msgid "%s/example.git"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:602
|
#: ./pkg/upstream/stack/stack.go:613
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s"
|
msgid "%s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -549,12 +549,12 @@ msgstr ""
|
|||||||
msgid "%s: waiting %d seconds before next retry"
|
msgid "%s: waiting %d seconds before next retry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:423
|
#: ./cli/app/upgrade.go:424
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a known version"
|
msgid "'%s' is not a known version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/rollback.go:303 ./cli/app/upgrade.go:418
|
#: ./cli/app/rollback.go:304 ./cli/app/upgrade.go:419
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a known version for %s"
|
msgid "'%s' is not a known version for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -621,7 +621,7 @@ msgstr ""
|
|||||||
msgid "Both local recipe and live deployment labels are shown."
|
msgid "Both local recipe and live deployment labels are shown."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/backup.go:319 ./cli/app/backup.go:335 ./cli/app/check.go:95 ./cli/app/cmd.go:285 ./cli/app/cp.go:385 ./cli/app/deploy.go:395 ./cli/app/labels.go:143 ./cli/app/new.go:397 ./cli/app/ps.go:213 ./cli/app/restart.go:162 ./cli/app/restore.go:138 ./cli/app/secret.go:569 ./cli/app/secret.go:609 ./cli/app/secret.go:633 ./cli/app/secret.go:641 ./cli/catalogue/catalogue.go:318 ./cli/recipe/lint.go:137
|
#: ./cli/app/backup.go:319 ./cli/app/backup.go:335 ./cli/app/check.go:95 ./cli/app/cmd.go:285 ./cli/app/cp.go:385 ./cli/app/deploy.go:396 ./cli/app/labels.go:143 ./cli/app/new.go:397 ./cli/app/ps.go:213 ./cli/app/restart.go:163 ./cli/app/restore.go:138 ./cli/app/secret.go:569 ./cli/app/secret.go:609 ./cli/app/secret.go:633 ./cli/app/secret.go:641 ./cli/catalogue/catalogue.go:318 ./cli/recipe/lint.go:137
|
||||||
msgid "C"
|
msgid "C"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -762,7 +762,7 @@ msgid "Creates a new app from a default recipe.\n"
|
|||||||
"on your $PATH."
|
"on your $PATH."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:411 ./cli/app/new.go:373 ./cli/app/rollback.go:360 ./cli/app/upgrade.go:469
|
#: ./cli/app/deploy.go:412 ./cli/app/new.go:373 ./cli/app/rollback.go:361 ./cli/app/upgrade.go:470
|
||||||
msgid "D"
|
msgid "D"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1469,7 +1469,7 @@ msgid "To load completions:\n"
|
|||||||
" # and source this file from your PowerShell profile."
|
" # and source this file from your PowerShell profile."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:435 ./cli/app/rollback.go:376 ./cli/app/upgrade.go:493
|
#: ./cli/app/deploy.go:436 ./cli/app/rollback.go:377 ./cli/app/upgrade.go:494
|
||||||
msgid "U"
|
msgid "U"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1676,7 +1676,7 @@ msgctxt "app backup list"
|
|||||||
msgid "a"
|
msgid "a"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:169
|
#: ./cli/app/restart.go:170
|
||||||
msgctxt "app restart"
|
msgctxt "app restart"
|
||||||
msgid "a"
|
msgid "a"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1785,7 +1785,7 @@ msgstr ""
|
|||||||
msgid "all tasks reached terminal state"
|
msgid "all tasks reached terminal state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:168
|
#: ./cli/app/restart.go:169
|
||||||
msgid "all-services"
|
msgid "all-services"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1844,7 +1844,7 @@ msgstr ""
|
|||||||
msgid "attempting to run %s"
|
msgid "attempting to run %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:272 ./cli/app/upgrade.go:295
|
#: ./cli/app/deploy.go:273 ./cli/app/upgrade.go:296
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "attempting to run post deploy commands, saw: %s"
|
msgid "attempting to run post deploy commands, saw: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1854,7 +1854,7 @@ msgstr ""
|
|||||||
msgid "attempting to scale %s to 0"
|
msgid "attempting to scale %s to 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:140
|
#: ./cli/app/restart.go:141
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "attempting to scale %s to 1"
|
msgid "attempting to scale %s to 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1924,7 +1924,7 @@ msgstr ""
|
|||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#. translators: `abra app cp` aliases. use a comma separated list of aliases with
|
#. translators: `abra app cp` aliases. use a comma separated list of aliases with
|
||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#: ./cli/app/backup.go:148 ./cli/app/cp.go:30 ./cli/app/deploy.go:419 ./cli/app/rollback.go:368 ./cli/app/upgrade.go:477
|
#: ./cli/app/backup.go:148 ./cli/app/cp.go:30 ./cli/app/deploy.go:420 ./cli/app/rollback.go:369 ./cli/app/upgrade.go:478
|
||||||
msgid "c"
|
msgid "c"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1965,7 +1965,7 @@ msgstr ""
|
|||||||
msgid "cannot find app with name %s"
|
msgid "cannot find app with name %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:657
|
#: ./pkg/upstream/stack/stack.go:668
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot get label %s for %s"
|
msgid "cannot get label %s for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1980,7 +1980,7 @@ msgstr ""
|
|||||||
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?"
|
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:369
|
#: ./cli/app/deploy.go:370
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?\n"
|
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?\n"
|
||||||
" to return to a regular release, specify a release tag, commit SHA or use \"--latest\""
|
" to return to a regular release, specify a release tag, commit SHA or use \"--latest\""
|
||||||
@ -1999,7 +1999,7 @@ msgstr ""
|
|||||||
msgid "cannot use '[secret] [version]' and '--all' together"
|
msgid "cannot use '[secret] [version]' and '--all' together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:311
|
#: ./cli/app/deploy.go:312
|
||||||
msgid "cannot use --chaos and --latest together"
|
msgid "cannot use --chaos and --latest together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2023,11 +2023,11 @@ msgstr ""
|
|||||||
msgid "cannot use [service] and --all-services/-a together"
|
msgid "cannot use [service] and --all-services/-a together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:303 ./cli/app/new.go:76
|
#: ./cli/app/deploy.go:304 ./cli/app/new.go:76
|
||||||
msgid "cannot use [version] and --chaos together"
|
msgid "cannot use [version] and --chaos together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:307
|
#: ./cli/app/deploy.go:308
|
||||||
msgid "cannot use [version] and --latest together"
|
msgid "cannot use [version] and --latest together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2059,7 +2059,7 @@ msgstr ""
|
|||||||
msgid "cfg"
|
msgid "cfg"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/backup.go:318 ./cli/app/backup.go:334 ./cli/app/check.go:94 ./cli/app/cmd.go:284 ./cli/app/cp.go:384 ./cli/app/deploy.go:394 ./cli/app/labels.go:142 ./cli/app/new.go:396 ./cli/app/ps.go:212 ./cli/app/restart.go:161 ./cli/app/restore.go:137 ./cli/app/secret.go:568 ./cli/app/secret.go:608 ./cli/app/secret.go:632 ./cli/app/secret.go:640 ./cli/catalogue/catalogue.go:317 ./cli/recipe/lint.go:136
|
#: ./cli/app/backup.go:318 ./cli/app/backup.go:334 ./cli/app/check.go:94 ./cli/app/cmd.go:284 ./cli/app/cp.go:384 ./cli/app/deploy.go:395 ./cli/app/labels.go:142 ./cli/app/new.go:396 ./cli/app/ps.go:212 ./cli/app/restart.go:162 ./cli/app/restore.go:137 ./cli/app/secret.go:568 ./cli/app/secret.go:608 ./cli/app/secret.go:632 ./cli/app/secret.go:640 ./cli/catalogue/catalogue.go:317 ./cli/recipe/lint.go:136
|
||||||
msgid "chaos"
|
msgid "chaos"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2068,7 +2068,7 @@ msgstr ""
|
|||||||
msgid "check <domain> [flags]"
|
msgid "check <domain> [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:94 ./cli/app/undeploy.go:58 ./cli/app/upgrade.go:441
|
#: ./cli/app/deploy.go:94 ./cli/app/undeploy.go:58 ./cli/app/upgrade.go:442
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "checking whether %s is already deployed"
|
msgid "checking whether %s is already deployed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2291,7 +2291,7 @@ msgstr ""
|
|||||||
msgid "create remote directory: %s"
|
msgid "create remote directory: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/client/client.go:102
|
#: ./pkg/client/client.go:111
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "created client for %s"
|
msgid "created client for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2311,7 +2311,7 @@ msgstr ""
|
|||||||
msgid "created the %s context"
|
msgid "created the %s context"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:520
|
#: ./pkg/upstream/stack/stack.go:524
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating %s"
|
msgid "creating %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2326,12 +2326,12 @@ msgstr ""
|
|||||||
msgid "creating context with domain %s"
|
msgid "creating context with domain %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:422
|
#: ./pkg/upstream/stack/stack.go:426
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating network %s"
|
msgid "creating network %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:369
|
#: ./pkg/upstream/stack/stack.go:373
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating secret %s"
|
msgid "creating secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2350,7 +2350,7 @@ msgstr ""
|
|||||||
msgid "critical errors present in %s config"
|
msgid "critical errors present in %s config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/rollback.go:298
|
#: ./cli/app/rollback.go:299
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "current deployment '%s' is not a known version for %s"
|
msgid "current deployment '%s' is not a known version for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2390,11 +2390,11 @@ msgstr ""
|
|||||||
msgid "deploy <domain> [version] [flags]"
|
msgid "deploy <domain> [version] [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:593
|
#: ./pkg/upstream/stack/stack.go:604
|
||||||
msgid "deploy failed 🛑"
|
msgid "deploy failed 🛑"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:597
|
#: ./pkg/upstream/stack/stack.go:608
|
||||||
msgid "deploy in progress 🟠"
|
msgid "deploy in progress 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2402,15 +2402,15 @@ msgstr ""
|
|||||||
msgid "deploy labels stanza present"
|
msgid "deploy labels stanza present"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:429
|
#: ./cli/app/deploy.go:430
|
||||||
msgid "deploy latest recipe version"
|
msgid "deploy latest recipe version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:637
|
#: ./pkg/upstream/stack/stack.go:648
|
||||||
msgid "deploy succeeded 🟢"
|
msgid "deploy succeeded 🟢"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:595
|
#: ./pkg/upstream/stack/stack.go:606
|
||||||
msgid "deploy timed out 🟠"
|
msgid "deploy timed out 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2504,11 +2504,11 @@ msgstr ""
|
|||||||
msgid "dirty: %v, "
|
msgid "dirty: %v, "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:421 ./cli/app/rollback.go:370 ./cli/app/upgrade.go:479
|
#: ./cli/app/deploy.go:422 ./cli/app/rollback.go:371 ./cli/app/upgrade.go:480
|
||||||
msgid "disable converge logic checks"
|
msgid "disable converge logic checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:413 ./cli/app/rollback.go:362 ./cli/app/upgrade.go:471
|
#: ./cli/app/deploy.go:414 ./cli/app/rollback.go:363 ./cli/app/upgrade.go:472
|
||||||
msgid "disable public DNS checks"
|
msgid "disable public DNS checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2726,7 +2726,7 @@ msgstr ""
|
|||||||
|
|
||||||
#. translators: `abra recipe fetch` aliases. use a comma separated list of aliases
|
#. translators: `abra recipe fetch` aliases. use a comma separated list of aliases
|
||||||
#. with no spaces in between
|
#. with no spaces in between
|
||||||
#: ./cli/app/deploy.go:403 ./cli/app/env.go:325 ./cli/app/remove.go:163 ./cli/app/rollback.go:352 ./cli/app/secret.go:593 ./cli/app/upgrade.go:461 ./cli/app/volume.go:217 ./cli/recipe/fetch.go:20 ./cli/recipe/fetch.go:138
|
#: ./cli/app/deploy.go:404 ./cli/app/env.go:325 ./cli/app/remove.go:163 ./cli/app/rollback.go:353 ./cli/app/secret.go:593 ./cli/app/upgrade.go:462 ./cli/app/volume.go:217 ./cli/recipe/fetch.go:20 ./cli/recipe/fetch.go:138
|
||||||
msgid "f"
|
msgid "f"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2760,22 +2760,22 @@ msgstr ""
|
|||||||
msgid "failed to copy %s from local machine to %s: output:%s err:%s"
|
msgid "failed to copy %s from local machine to %s: output:%s err:%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:531
|
#: ./pkg/upstream/stack/stack.go:535
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create %s"
|
msgid "failed to create %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:393
|
#: ./pkg/upstream/stack/stack.go:397
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create config %s"
|
msgid "failed to create config %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:424
|
#: ./pkg/upstream/stack/stack.go:428
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create network %s"
|
msgid "failed to create network %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:371
|
#: ./pkg/upstream/stack/stack.go:375
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create secret %s"
|
msgid "failed to create secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2872,7 +2872,7 @@ msgstr ""
|
|||||||
msgid "failed to retrieve latest commit for %s: %s"
|
msgid "failed to retrieve latest commit for %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:468
|
#: ./pkg/upstream/stack/stack.go:472
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to retrieve registry auth for image %s: %s"
|
msgid "failed to retrieve registry auth for image %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2892,17 +2892,17 @@ msgstr ""
|
|||||||
msgid "failed to tag release: %s"
|
msgid "failed to tag release: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:508
|
#: ./pkg/upstream/stack/stack.go:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update %s"
|
msgid "failed to update %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:387
|
#: ./pkg/upstream/stack/stack.go:391
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update config %s"
|
msgid "failed to update config %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:365
|
#: ./pkg/upstream/stack/stack.go:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update secret %s"
|
msgid "failed to update secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2957,7 +2957,7 @@ msgstr ""
|
|||||||
msgid "final merged env values for %s are: %s"
|
msgid "final merged env values for %s are: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:402 ./cli/app/env.go:324 ./cli/app/remove.go:162 ./cli/app/rollback.go:351 ./cli/app/upgrade.go:460 ./cli/app/volume.go:216 ./cli/recipe/fetch.go:137
|
#: ./cli/app/deploy.go:403 ./cli/app/env.go:324 ./cli/app/remove.go:162 ./cli/app/rollback.go:352 ./cli/app/upgrade.go:461 ./cli/app/volume.go:216 ./cli/recipe/fetch.go:137
|
||||||
msgid "force"
|
msgid "force"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3171,7 +3171,7 @@ msgstr ""
|
|||||||
msgid "id: %s, "
|
msgid "id: %s, "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/backup.go:321 ./cli/app/backup.go:337 ./cli/app/check.go:97 ./cli/app/cmd.go:287 ./cli/app/cp.go:387 ./cli/app/deploy.go:397 ./cli/app/labels.go:145 ./cli/app/new.go:399 ./cli/app/ps.go:215 ./cli/app/restart.go:164 ./cli/app/restore.go:140 ./cli/app/secret.go:571 ./cli/app/secret.go:611 ./cli/app/secret.go:635 ./cli/app/secret.go:643 ./cli/catalogue/catalogue.go:320 ./cli/recipe/lint.go:139
|
#: ./cli/app/backup.go:321 ./cli/app/backup.go:337 ./cli/app/check.go:97 ./cli/app/cmd.go:287 ./cli/app/cp.go:387 ./cli/app/deploy.go:398 ./cli/app/labels.go:145 ./cli/app/new.go:399 ./cli/app/ps.go:215 ./cli/app/restart.go:165 ./cli/app/restore.go:140 ./cli/app/secret.go:571 ./cli/app/secret.go:611 ./cli/app/secret.go:635 ./cli/app/secret.go:643 ./cli/catalogue/catalogue.go:320 ./cli/recipe/lint.go:139
|
||||||
msgid "ignore uncommitted recipes changes"
|
msgid "ignore uncommitted recipes changes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3282,7 +3282,7 @@ msgstr ""
|
|||||||
msgid "initialised new git repo in %s"
|
msgid "initialised new git repo in %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:206
|
#: ./pkg/upstream/stack/stack.go:207
|
||||||
msgid "initialising deployment"
|
msgid "initialising deployment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3346,7 +3346,7 @@ msgstr ""
|
|||||||
msgid "invalid npipe source, source cannot be empty"
|
msgid "invalid npipe source, source cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:239
|
#: ./pkg/upstream/stack/stack.go:241
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid option %s for flag --resolve-image"
|
msgid "invalid option %s for flag --resolve-image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3369,7 +3369,7 @@ msgstr ""
|
|||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#. translators: `abra recipe lint` aliases. use a comma separated list of
|
#. translators: `abra recipe lint` aliases. use a comma separated list of
|
||||||
#. aliases with no spaces in between
|
#. aliases with no spaces in between
|
||||||
#: ./cli/app/cmd.go:261 ./cli/app/deploy.go:427 ./cli/app/logs.go:20 ./cli/recipe/lint.go:17 ./cli/server/add.go:207
|
#: ./cli/app/cmd.go:261 ./cli/app/deploy.go:428 ./cli/app/logs.go:20 ./cli/recipe/lint.go:17 ./cli/server/add.go:207
|
||||||
msgid "l"
|
msgid "l"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3384,7 +3384,7 @@ msgstr ""
|
|||||||
msgid "labels <domain> [flags]"
|
msgid "labels <domain> [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:426 ./cli/app/list.go:182
|
#: ./cli/app/deploy.go:427 ./cli/app/list.go:182
|
||||||
msgid "latest"
|
msgid "latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3473,12 +3473,12 @@ msgstr ""
|
|||||||
msgid "logs <domain> [service] [flags]"
|
msgid "logs <domain> [service] [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:628
|
#: ./pkg/upstream/stack/stack.go:639
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "logs: %s"
|
msgid "logs: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:630
|
#: ./pkg/upstream/stack/stack.go:641
|
||||||
msgid "logs: no log output received from deployment"
|
msgid "logs: no log output received from deployment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3614,12 +3614,12 @@ msgstr ""
|
|||||||
msgid "need 3 or 4 arguments"
|
msgid "need 3 or 4 arguments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:348
|
#: ./pkg/upstream/stack/stack.go:352
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed, which you can do by running this on the server: docker network create -d overlay proxy"
|
msgid "network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed, which you can do by running this on the server: docker network create -d overlay proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:352
|
#: ./pkg/upstream/stack/stack.go:356
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\""
|
msgid "network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3842,11 +3842,11 @@ msgstr ""
|
|||||||
msgid "no volumes to remove"
|
msgid "no volumes to remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:418 ./cli/app/rollback.go:367 ./cli/app/upgrade.go:476
|
#: ./cli/app/deploy.go:419 ./cli/app/rollback.go:368 ./cli/app/upgrade.go:477
|
||||||
msgid "no-converge-checks"
|
msgid "no-converge-checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:410 ./cli/app/rollback.go:359 ./cli/app/upgrade.go:468
|
#: ./cli/app/deploy.go:411 ./cli/app/rollback.go:360 ./cli/app/upgrade.go:469
|
||||||
msgid "no-domain-checks"
|
msgid "no-domain-checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3902,7 +3902,7 @@ msgstr ""
|
|||||||
msgid "only show errors"
|
msgid "only show errors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:487
|
#: ./cli/app/upgrade.go:488
|
||||||
msgid "only show release notes"
|
msgid "only show release notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3933,22 +3933,22 @@ msgstr ""
|
|||||||
msgid "parsed following command arguments: %s"
|
msgid "parsed following command arguments: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:344
|
#: ./cli/app/upgrade.go:345
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing chosen upgrade version failed: %s"
|
msgid "parsing chosen upgrade version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:388
|
#: ./cli/app/upgrade.go:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing deployed version failed: %s"
|
msgid "parsing deployed version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:349
|
#: ./cli/app/upgrade.go:350
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing deployment version failed: %s"
|
msgid "parsing deployment version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:355 ./cli/app/upgrade.go:394
|
#: ./cli/app/upgrade.go:356 ./cli/app/upgrade.go:395
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing recipe version failed: %s"
|
msgid "parsing recipe version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3973,7 +3973,7 @@ msgstr ""
|
|||||||
msgid "pattern"
|
msgid "pattern"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:405 ./cli/app/env.go:327 ./cli/app/remove.go:165 ./cli/app/rollback.go:354 ./cli/app/upgrade.go:463 ./cli/app/volume.go:219
|
#: ./cli/app/deploy.go:406 ./cli/app/env.go:327 ./cli/app/remove.go:165 ./cli/app/rollback.go:355 ./cli/app/upgrade.go:464 ./cli/app/volume.go:219
|
||||||
msgid "perform action without further prompt"
|
msgid "perform action without further prompt"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3988,27 +3988,27 @@ msgstr ""
|
|||||||
msgid "please fix your synced label for %s and re-run this command"
|
msgid "please fix your synced label for %s and re-run this command"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/rollback.go:266
|
#: ./cli/app/rollback.go:267
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select a downgrade (version: %s):"
|
msgid "please select a downgrade (version: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/rollback.go:271
|
#: ./cli/app/rollback.go:272
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select a downgrade (version: %s, chaos: %s):"
|
msgid "please select a downgrade (version: %s, chaos: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:311
|
#: ./cli/app/upgrade.go:312
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select an upgrade (version: %s):"
|
msgid "please select an upgrade (version: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:316
|
#: ./cli/app/upgrade.go:317
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select an upgrade (version: %s, chaos: %s):"
|
msgid "please select an upgrade (version: %s, chaos: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:576
|
#: ./pkg/upstream/stack/stack.go:587
|
||||||
msgid "polling deployment status"
|
msgid "polling deployment status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4094,7 +4094,7 @@ msgstr ""
|
|||||||
#. with no spaces in between
|
#. with no spaces in between
|
||||||
#. translators: `abra recipe` aliases. use a comma separated list of aliases
|
#. translators: `abra recipe` aliases. use a comma separated list of aliases
|
||||||
#. with no spaces in between
|
#. with no spaces in between
|
||||||
#: ./cli/app/backup.go:327 ./cli/app/list.go:300 ./cli/app/move.go:350 ./cli/app/run.go:23 ./cli/app/upgrade.go:485 ./cli/catalogue/catalogue.go:302 ./cli/recipe/recipe.go:12 ./cli/recipe/release.go:649 ./cli/recipe/sync.go:272
|
#: ./cli/app/backup.go:327 ./cli/app/list.go:300 ./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:649 ./cli/recipe/sync.go:272
|
||||||
msgid "r"
|
msgid "r"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4210,7 +4210,7 @@ msgstr ""
|
|||||||
msgid "release <recipe> [version] [flags]"
|
msgid "release <recipe> [version] [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/upgrade.go:484
|
#: ./cli/app/upgrade.go:485
|
||||||
msgid "releasenotes"
|
msgid "releasenotes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4376,7 +4376,7 @@ msgstr ""
|
|||||||
msgid "restart <domain> [[service] | --all-services] [flags]"
|
msgid "restart <domain> [[service] | --all-services] [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/restart.go:171
|
#: ./cli/app/restart.go:172
|
||||||
msgid "restart all services"
|
msgid "restart all services"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4441,7 +4441,7 @@ msgstr ""
|
|||||||
msgid "retrieved versions from local recipe repository"
|
msgid "retrieved versions from local recipe repository"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:464
|
#: ./pkg/upstream/stack/stack.go:468
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "retrieving docker auth token: failed create docker cli: %s"
|
msgid "retrieving docker auth token: failed create docker cli: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4514,7 +4514,7 @@ msgstr ""
|
|||||||
msgid "run command locally"
|
msgid "run command locally"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:270 ./cli/app/upgrade.go:292
|
#: ./cli/app/deploy.go:271 ./cli/app/upgrade.go:293
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "run the following post-deploy commands: %s"
|
msgid "run the following post-deploy commands: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4599,12 +4599,12 @@ msgstr ""
|
|||||||
msgid "secret not found: %s"
|
msgid "secret not found: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:339
|
#: ./cli/app/deploy.go:340
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret not generated: %s"
|
msgid "secret not generated: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:337
|
#: ./cli/app/deploy.go:338
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret not inserted (#generate=false): %s"
|
msgid "secret not inserted (#generate=false): %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4651,11 +4651,21 @@ msgstr ""
|
|||||||
msgid "server doesn't exist?"
|
msgid "server doesn't exist?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/client/client.go:48
|
#: ./pkg/client/client.go:54
|
||||||
|
#, c-format
|
||||||
|
msgid "server missing context, context creation failed: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ./pkg/client/client.go:59
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "server missing context, run \"abra server add %s\"?"
|
msgid "server missing context, run \"abra server add %s\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ./pkg/client/client.go:48
|
||||||
|
#, c-format
|
||||||
|
msgid "server missing, run \"abra server add %s\"?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/server/add.go:148
|
#: ./cli/server/add.go:148
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup"
|
msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup"
|
||||||
@ -4728,7 +4738,7 @@ msgstr ""
|
|||||||
msgid "severity"
|
msgid "severity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:437 ./cli/app/rollback.go:378 ./cli/app/upgrade.go:495
|
#: ./cli/app/deploy.go:438 ./cli/app/rollback.go:379 ./cli/app/upgrade.go:496
|
||||||
msgid "show all configs & images, including unchanged ones"
|
msgid "show all configs & images, including unchanged ones"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4752,7 +4762,7 @@ msgstr ""
|
|||||||
msgid "show debug messages"
|
msgid "show debug messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:434 ./cli/app/rollback.go:375 ./cli/app/upgrade.go:492
|
#: ./cli/app/deploy.go:435 ./cli/app/rollback.go:376 ./cli/app/upgrade.go:493
|
||||||
msgid "show-unchanged"
|
msgid "show-unchanged"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4796,7 +4806,7 @@ msgstr ""
|
|||||||
msgid "skipping as requested, undeploy still in progress 🟠"
|
msgid "skipping as requested, undeploy still in progress 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:306
|
#: ./pkg/upstream/stack/stack.go:309
|
||||||
msgid "skipping converge logic checks"
|
msgid "skipping converge logic checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4818,12 +4828,12 @@ msgstr ""
|
|||||||
msgid "skipping secret (because it already exists) on %s: %s"
|
msgid "skipping secret (because it already exists) on %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/app/app.go:692
|
#: ./pkg/app/app.go:697
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "skipping version %s write as already exists in %s.env"
|
msgid "skipping version %s write as already exists in %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/app/app.go:686
|
#: ./pkg/app/app.go:691
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "skipping writing version %s because dry run"
|
msgid "skipping writing version %s because dry run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4931,12 +4941,12 @@ msgstr ""
|
|||||||
msgid "successfully created %s"
|
msgid "successfully created %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/client/client.go:111
|
#: ./pkg/client/client.go:120
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "swarm mode not enabled on %s?"
|
msgid "swarm mode not enabled on %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/client/client.go:114
|
#: ./pkg/client/client.go:123
|
||||||
msgid "swarm mode not enabled on local server?"
|
msgid "swarm mode not enabled on local server?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5012,7 +5022,7 @@ msgstr ""
|
|||||||
msgid "timeout label: %s"
|
msgid "timeout label: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/remove.go:29 ./pkg/upstream/stack/stack.go:209
|
#: ./pkg/upstream/stack/remove.go:29 ./pkg/upstream/stack/stack.go:210
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "timeout: set to %d second(s)"
|
msgid "timeout: set to %d second(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5435,11 +5445,6 @@ msgstr ""
|
|||||||
msgid "unknown server %s, run \"abra server add %s\"?"
|
msgid "unknown server %s, run \"abra server add %s\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/client/client.go:51
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown server, run \"abra server add %s\"?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ./cli/app/cp.go:259
|
#: ./cli/app/cp.go:259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "untar: %s"
|
msgid "untar: %s"
|
||||||
@ -5451,7 +5456,7 @@ msgstr ""
|
|||||||
msgid "up"
|
msgid "up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:473
|
#: ./pkg/upstream/stack/stack.go:477
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "updating %s"
|
msgid "updating %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5563,7 +5568,7 @@ msgstr ""
|
|||||||
msgid "version"
|
msgid "version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/app/app.go:690
|
#: ./pkg/app/app.go:695
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version %s saved to %s.env"
|
msgid "version %s saved to %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5582,6 +5587,10 @@ msgstr ""
|
|||||||
msgid "version for abra"
|
msgid "version for abra"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ./pkg/app/app.go:637
|
||||||
|
msgid "version is unknown, skipping env write"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/recipe/recipe.go:130
|
#: ./pkg/recipe/recipe.go:130
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version seems invalid: %s"
|
msgid "version seems invalid: %s"
|
||||||
@ -5592,27 +5601,27 @@ msgstr ""
|
|||||||
msgid "version wiped from %s.env"
|
msgid "version wiped from %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:353
|
#: ./cli/app/deploy.go:354
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking chaos version: %s"
|
msgid "version: taking chaos version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:379
|
#: ./cli/app/deploy.go:380
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking deployed version: %s"
|
msgid "version: taking deployed version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:384
|
#: ./cli/app/deploy.go:385
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking new recipe version: %s"
|
msgid "version: taking new recipe version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:373
|
#: ./cli/app/deploy.go:374
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking version from .env file: %s"
|
msgid "version: taking version from .env file: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:359
|
#: ./cli/app/deploy.go:360
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking version from cli arg: %s"
|
msgid "version: taking version from cli arg: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5672,22 +5681,22 @@ msgstr ""
|
|||||||
msgid "volumes pruned: %d; space reclaimed: %s"
|
msgid "volumes pruned: %d; space reclaimed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:614
|
#: ./pkg/upstream/stack/stack.go:625
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error creating log dir: %s"
|
msgid "waitOnServices: error creating log dir: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:619
|
#: ./pkg/upstream/stack/stack.go:630
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error opening file: %s"
|
msgid "waitOnServices: error opening file: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:585
|
#: ./pkg/upstream/stack/stack.go:596
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error running TUI: %s"
|
msgid "waitOnServices: error running TUI: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./pkg/upstream/stack/stack.go:625
|
#: ./pkg/upstream/stack/stack.go:636
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: writeFile: %s"
|
msgid "waitOnServices: writeFile: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5735,7 +5744,7 @@ msgstr ""
|
|||||||
msgid "writer: %v, "
|
msgid "writer: %v, "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ./cli/app/deploy.go:277 ./cli/app/new.go:241 ./cli/app/rollback.go:255 ./cli/app/undeploy.go:120 ./cli/app/upgrade.go:300
|
#: ./cli/app/deploy.go:278 ./cli/app/new.go:241 ./cli/app/rollback.go:256 ./cli/app/undeploy.go:120 ./cli/app/upgrade.go:301
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "writing recipe version failed: %s"
|
msgid "writing recipe version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -2,7 +2,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL\n"
|
"Report-Msgid-Bugs-To: EMAIL\n"
|
||||||
"POT-Creation-Date: 2025-11-02 11:41+0100\n"
|
"POT-Creation-Date: 2025-11-04 15:34+0100\n"
|
||||||
"PO-Revision-Date: 2025-09-04 08:14+0000\n"
|
"PO-Revision-Date: 2025-09-04 08:14+0000\n"
|
||||||
"Last-Translator: chasqui <chasqui@cryptolab.net>\n"
|
"Last-Translator: chasqui <chasqui@cryptolab.net>\n"
|
||||||
"Language-Team: Spanish <https://translate.coopcloud.tech/projects/co-op-cloud/abra/es/>\n"
|
"Language-Team: Spanish <https://translate.coopcloud.tech/projects/co-op-cloud/abra/es/>\n"
|
||||||
@ -285,12 +285,12 @@ msgstr ""
|
|||||||
msgid "%s has been detected as not deployed"
|
msgid "%s has been detected as not deployed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:139
|
#: cli/app/restart.go:140
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s has been scaled to 0"
|
msgid "%s has been scaled to 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:150
|
#: cli/app/restart.go:151
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s has been scaled to 1"
|
msgid "%s has been scaled to 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -350,19 +350,19 @@ msgstr ""
|
|||||||
msgid "%s is missing the TYPE env var?"
|
msgid "%s is missing the TYPE env var?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/rollback.go:308 cli/app/rollback.go:312
|
#: cli/app/rollback.go:309 cli/app/rollback.go:313
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not a downgrade for %s?"
|
msgid "%s is not a downgrade for %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:428 cli/app/upgrade.go:432
|
#: cli/app/upgrade.go:429 cli/app/upgrade.go:433
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not an upgrade for %s?"
|
msgid "%s is not an upgrade for %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/env.go:146 cli/app/logs.go:65 cli/app/ps.go:62
|
#: cli/app/env.go:146 cli/app/logs.go:65 cli/app/ps.go:62
|
||||||
#: cli/app/restart.go:100 cli/app/services.go:55 cli/app/undeploy.go:66
|
#: cli/app/restart.go:100 cli/app/services.go:55 cli/app/undeploy.go:66
|
||||||
#: cli/app/upgrade.go:449
|
#: cli/app/upgrade.go:450
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s is not deployed?"
|
msgid "%s is not deployed?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -437,7 +437,7 @@ msgstr ""
|
|||||||
msgid "%s service is missing image tag?"
|
msgid "%s service is missing image tag?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:151
|
#: cli/app/restart.go:152
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s service successfully restarted"
|
msgid "%s service successfully restarted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -472,7 +472,7 @@ msgstr ""
|
|||||||
msgid "%s/example.git"
|
msgid "%s/example.git"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:602
|
#: pkg/upstream/stack/stack.go:613
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s"
|
msgid "%s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -562,12 +562,12 @@ msgstr ""
|
|||||||
msgid "%s: waiting %d seconds before next retry"
|
msgid "%s: waiting %d seconds before next retry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:423
|
#: cli/app/upgrade.go:424
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a known version"
|
msgid "'%s' is not a known version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/rollback.go:303 cli/app/upgrade.go:418
|
#: cli/app/rollback.go:304 cli/app/upgrade.go:419
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a known version for %s"
|
msgid "'%s' is not a known version for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -637,9 +637,9 @@ msgid "Both local recipe and live deployment labels are shown."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/backup.go:319 cli/app/backup.go:335 cli/app/check.go:95
|
#: cli/app/backup.go:319 cli/app/backup.go:335 cli/app/check.go:95
|
||||||
#: cli/app/cmd.go:285 cli/app/cp.go:385 cli/app/deploy.go:395
|
#: cli/app/cmd.go:285 cli/app/cp.go:385 cli/app/deploy.go:396
|
||||||
#: cli/app/labels.go:143 cli/app/new.go:397 cli/app/ps.go:213
|
#: cli/app/labels.go:143 cli/app/new.go:397 cli/app/ps.go:213
|
||||||
#: cli/app/restart.go:162 cli/app/restore.go:138 cli/app/secret.go:569
|
#: cli/app/restart.go:163 cli/app/restore.go:138 cli/app/secret.go:569
|
||||||
#: cli/app/secret.go:609 cli/app/secret.go:633 cli/app/secret.go:641
|
#: cli/app/secret.go:609 cli/app/secret.go:633 cli/app/secret.go:641
|
||||||
#: cli/catalogue/catalogue.go:318 cli/recipe/lint.go:137
|
#: cli/catalogue/catalogue.go:318 cli/recipe/lint.go:137
|
||||||
msgid "C"
|
msgid "C"
|
||||||
@ -785,8 +785,8 @@ msgid ""
|
|||||||
"on your $PATH."
|
"on your $PATH."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:411 cli/app/new.go:373 cli/app/rollback.go:360
|
#: cli/app/deploy.go:412 cli/app/new.go:373 cli/app/rollback.go:361
|
||||||
#: cli/app/upgrade.go:469
|
#: cli/app/upgrade.go:470
|
||||||
msgid "D"
|
msgid "D"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1518,7 +1518,7 @@ msgid ""
|
|||||||
" # and source this file from your PowerShell profile."
|
" # and source this file from your PowerShell profile."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:435 cli/app/rollback.go:376 cli/app/upgrade.go:493
|
#: cli/app/deploy.go:436 cli/app/rollback.go:377 cli/app/upgrade.go:494
|
||||||
msgid "U"
|
msgid "U"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1734,7 +1734,7 @@ msgctxt "app backup list"
|
|||||||
msgid "a"
|
msgid "a"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:169
|
#: cli/app/restart.go:170
|
||||||
msgctxt "app restart"
|
msgctxt "app restart"
|
||||||
msgid "a"
|
msgid "a"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1844,7 +1844,7 @@ msgstr ""
|
|||||||
msgid "all tasks reached terminal state"
|
msgid "all tasks reached terminal state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:168
|
#: cli/app/restart.go:169
|
||||||
msgid "all-services"
|
msgid "all-services"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1903,7 +1903,7 @@ msgstr ""
|
|||||||
msgid "attempting to run %s"
|
msgid "attempting to run %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:272 cli/app/upgrade.go:295
|
#: cli/app/deploy.go:273 cli/app/upgrade.go:296
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "attempting to run post deploy commands, saw: %s"
|
msgid "attempting to run post deploy commands, saw: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1913,7 +1913,7 @@ msgstr ""
|
|||||||
msgid "attempting to scale %s to 0"
|
msgid "attempting to scale %s to 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/restart.go:140
|
#: cli/app/restart.go:141
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "attempting to scale %s to 1"
|
msgid "attempting to scale %s to 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1989,8 +1989,8 @@ msgstr ""
|
|||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#. translators: `abra app cp` aliases. use a comma separated list of aliases with
|
#. translators: `abra app cp` aliases. use a comma separated list of aliases with
|
||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#: cli/app/backup.go:148 cli/app/cp.go:30 cli/app/deploy.go:419
|
#: cli/app/backup.go:148 cli/app/cp.go:30 cli/app/deploy.go:420
|
||||||
#: cli/app/rollback.go:368 cli/app/upgrade.go:477
|
#: cli/app/rollback.go:369 cli/app/upgrade.go:478
|
||||||
msgid "c"
|
msgid "c"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2031,7 +2031,7 @@ msgstr ""
|
|||||||
msgid "cannot find app with name %s"
|
msgid "cannot find app with name %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:657
|
#: pkg/upstream/stack/stack.go:668
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot get label %s for %s"
|
msgid "cannot get label %s for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2046,7 +2046,7 @@ msgstr ""
|
|||||||
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?"
|
msgid "cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:369
|
#: cli/app/deploy.go:370
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?\n"
|
"cannot redeploy previous chaos version (%s), did you mean to use \"--chaos\"?\n"
|
||||||
@ -2066,7 +2066,7 @@ msgstr ""
|
|||||||
msgid "cannot use '[secret] [version]' and '--all' together"
|
msgid "cannot use '[secret] [version]' and '--all' together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:311
|
#: cli/app/deploy.go:312
|
||||||
msgid "cannot use --chaos and --latest together"
|
msgid "cannot use --chaos and --latest together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2090,11 +2090,11 @@ msgstr ""
|
|||||||
msgid "cannot use [service] and --all-services/-a together"
|
msgid "cannot use [service] and --all-services/-a together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:303 cli/app/new.go:76
|
#: cli/app/deploy.go:304 cli/app/new.go:76
|
||||||
msgid "cannot use [version] and --chaos together"
|
msgid "cannot use [version] and --chaos together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:307
|
#: cli/app/deploy.go:308
|
||||||
msgid "cannot use [version] and --latest together"
|
msgid "cannot use [version] and --latest together"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2127,9 +2127,9 @@ msgid "cfg"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/backup.go:318 cli/app/backup.go:334 cli/app/check.go:94
|
#: cli/app/backup.go:318 cli/app/backup.go:334 cli/app/check.go:94
|
||||||
#: cli/app/cmd.go:284 cli/app/cp.go:384 cli/app/deploy.go:394
|
#: cli/app/cmd.go:284 cli/app/cp.go:384 cli/app/deploy.go:395
|
||||||
#: cli/app/labels.go:142 cli/app/new.go:396 cli/app/ps.go:212
|
#: cli/app/labels.go:142 cli/app/new.go:396 cli/app/ps.go:212
|
||||||
#: cli/app/restart.go:161 cli/app/restore.go:137 cli/app/secret.go:568
|
#: cli/app/restart.go:162 cli/app/restore.go:137 cli/app/secret.go:568
|
||||||
#: cli/app/secret.go:608 cli/app/secret.go:632 cli/app/secret.go:640
|
#: cli/app/secret.go:608 cli/app/secret.go:632 cli/app/secret.go:640
|
||||||
#: cli/catalogue/catalogue.go:317 cli/recipe/lint.go:136
|
#: cli/catalogue/catalogue.go:317 cli/recipe/lint.go:136
|
||||||
msgid "chaos"
|
msgid "chaos"
|
||||||
@ -2140,7 +2140,7 @@ msgstr ""
|
|||||||
msgid "check <domain> [flags]"
|
msgid "check <domain> [flags]"
|
||||||
msgstr "verificar <domain> [flags]"
|
msgstr "verificar <domain> [flags]"
|
||||||
|
|
||||||
#: cli/app/deploy.go:94 cli/app/undeploy.go:58 cli/app/upgrade.go:441
|
#: cli/app/deploy.go:94 cli/app/undeploy.go:58 cli/app/upgrade.go:442
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "checking whether %s is already deployed"
|
msgid "checking whether %s is already deployed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2363,7 +2363,7 @@ msgstr ""
|
|||||||
msgid "create remote directory: %s"
|
msgid "create remote directory: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/client/client.go:102
|
#: pkg/client/client.go:111
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "created client for %s"
|
msgid "created client for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2383,7 +2383,7 @@ msgstr ""
|
|||||||
msgid "created the %s context"
|
msgid "created the %s context"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:520
|
#: pkg/upstream/stack/stack.go:524
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating %s"
|
msgid "creating %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2398,12 +2398,12 @@ msgstr ""
|
|||||||
msgid "creating context with domain %s"
|
msgid "creating context with domain %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:422
|
#: pkg/upstream/stack/stack.go:426
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating network %s"
|
msgid "creating network %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:369
|
#: pkg/upstream/stack/stack.go:373
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "creating secret %s"
|
msgid "creating secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2422,7 +2422,7 @@ msgstr ""
|
|||||||
msgid "critical errors present in %s config"
|
msgid "critical errors present in %s config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/rollback.go:298
|
#: cli/app/rollback.go:299
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "current deployment '%s' is not a known version for %s"
|
msgid "current deployment '%s' is not a known version for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2462,11 +2462,11 @@ msgstr ""
|
|||||||
msgid "deploy <domain> [version] [flags]"
|
msgid "deploy <domain> [version] [flags]"
|
||||||
msgstr "desplegar <domain> [version] [flags]"
|
msgstr "desplegar <domain> [version] [flags]"
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:593
|
#: pkg/upstream/stack/stack.go:604
|
||||||
msgid "deploy failed 🛑"
|
msgid "deploy failed 🛑"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:597
|
#: pkg/upstream/stack/stack.go:608
|
||||||
msgid "deploy in progress 🟠"
|
msgid "deploy in progress 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2474,16 +2474,16 @@ msgstr ""
|
|||||||
msgid "deploy labels stanza present"
|
msgid "deploy labels stanza present"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:429
|
#: cli/app/deploy.go:430
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "deploy latest recipe version"
|
msgid "deploy latest recipe version"
|
||||||
msgstr "Publicar una nueva versión de una receta"
|
msgstr "Publicar una nueva versión de una receta"
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:637
|
#: pkg/upstream/stack/stack.go:648
|
||||||
msgid "deploy succeeded 🟢"
|
msgid "deploy succeeded 🟢"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:595
|
#: pkg/upstream/stack/stack.go:606
|
||||||
msgid "deploy timed out 🟠"
|
msgid "deploy timed out 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2577,11 +2577,11 @@ msgstr ""
|
|||||||
msgid "dirty: %v, "
|
msgid "dirty: %v, "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:421 cli/app/rollback.go:370 cli/app/upgrade.go:479
|
#: cli/app/deploy.go:422 cli/app/rollback.go:371 cli/app/upgrade.go:480
|
||||||
msgid "disable converge logic checks"
|
msgid "disable converge logic checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:413 cli/app/rollback.go:362 cli/app/upgrade.go:471
|
#: cli/app/deploy.go:414 cli/app/rollback.go:363 cli/app/upgrade.go:472
|
||||||
msgid "disable public DNS checks"
|
msgid "disable public DNS checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2803,8 +2803,8 @@ msgstr ""
|
|||||||
|
|
||||||
#. translators: `abra recipe fetch` aliases. use a comma separated list of aliases
|
#. translators: `abra recipe fetch` aliases. use a comma separated list of aliases
|
||||||
#. with no spaces in between
|
#. with no spaces in between
|
||||||
#: cli/app/deploy.go:403 cli/app/env.go:325 cli/app/remove.go:163
|
#: cli/app/deploy.go:404 cli/app/env.go:325 cli/app/remove.go:163
|
||||||
#: cli/app/rollback.go:352 cli/app/secret.go:593 cli/app/upgrade.go:461
|
#: cli/app/rollback.go:353 cli/app/secret.go:593 cli/app/upgrade.go:462
|
||||||
#: cli/app/volume.go:217 cli/recipe/fetch.go:20 cli/recipe/fetch.go:138
|
#: cli/app/volume.go:217 cli/recipe/fetch.go:20 cli/recipe/fetch.go:138
|
||||||
msgid "f"
|
msgid "f"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2839,22 +2839,22 @@ msgstr ""
|
|||||||
msgid "failed to copy %s from local machine to %s: output:%s err:%s"
|
msgid "failed to copy %s from local machine to %s: output:%s err:%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:531
|
#: pkg/upstream/stack/stack.go:535
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create %s"
|
msgid "failed to create %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:393
|
#: pkg/upstream/stack/stack.go:397
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create config %s"
|
msgid "failed to create config %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:424
|
#: pkg/upstream/stack/stack.go:428
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create network %s"
|
msgid "failed to create network %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:371
|
#: pkg/upstream/stack/stack.go:375
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to create secret %s"
|
msgid "failed to create secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2951,7 +2951,7 @@ msgstr ""
|
|||||||
msgid "failed to retrieve latest commit for %s: %s"
|
msgid "failed to retrieve latest commit for %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:468
|
#: pkg/upstream/stack/stack.go:472
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to retrieve registry auth for image %s: %s"
|
msgid "failed to retrieve registry auth for image %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2971,17 +2971,17 @@ msgstr "🥷 Genera secretos (contraseñas) automáticamente 🤖"
|
|||||||
msgid "failed to tag release: %s"
|
msgid "failed to tag release: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:508
|
#: pkg/upstream/stack/stack.go:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update %s"
|
msgid "failed to update %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:387
|
#: pkg/upstream/stack/stack.go:391
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update config %s"
|
msgid "failed to update config %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:365
|
#: pkg/upstream/stack/stack.go:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to update secret %s"
|
msgid "failed to update secret %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3036,8 +3036,8 @@ msgstr ""
|
|||||||
msgid "final merged env values for %s are: %s"
|
msgid "final merged env values for %s are: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:402 cli/app/env.go:324 cli/app/remove.go:162
|
#: cli/app/deploy.go:403 cli/app/env.go:324 cli/app/remove.go:162
|
||||||
#: cli/app/rollback.go:351 cli/app/upgrade.go:460 cli/app/volume.go:216
|
#: cli/app/rollback.go:352 cli/app/upgrade.go:461 cli/app/volume.go:216
|
||||||
#: cli/recipe/fetch.go:137
|
#: cli/recipe/fetch.go:137
|
||||||
msgid "force"
|
msgid "force"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3254,9 +3254,9 @@ msgid "id: %s, "
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/backup.go:321 cli/app/backup.go:337 cli/app/check.go:97
|
#: cli/app/backup.go:321 cli/app/backup.go:337 cli/app/check.go:97
|
||||||
#: cli/app/cmd.go:287 cli/app/cp.go:387 cli/app/deploy.go:397
|
#: cli/app/cmd.go:287 cli/app/cp.go:387 cli/app/deploy.go:398
|
||||||
#: cli/app/labels.go:145 cli/app/new.go:399 cli/app/ps.go:215
|
#: cli/app/labels.go:145 cli/app/new.go:399 cli/app/ps.go:215
|
||||||
#: cli/app/restart.go:164 cli/app/restore.go:140 cli/app/secret.go:571
|
#: cli/app/restart.go:165 cli/app/restore.go:140 cli/app/secret.go:571
|
||||||
#: cli/app/secret.go:611 cli/app/secret.go:635 cli/app/secret.go:643
|
#: cli/app/secret.go:611 cli/app/secret.go:635 cli/app/secret.go:643
|
||||||
#: cli/catalogue/catalogue.go:320 cli/recipe/lint.go:139
|
#: cli/catalogue/catalogue.go:320 cli/recipe/lint.go:139
|
||||||
msgid "ignore uncommitted recipes changes"
|
msgid "ignore uncommitted recipes changes"
|
||||||
@ -3369,7 +3369,7 @@ msgstr ""
|
|||||||
msgid "initialised new git repo in %s"
|
msgid "initialised new git repo in %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:206
|
#: pkg/upstream/stack/stack.go:207
|
||||||
msgid "initialising deployment"
|
msgid "initialising deployment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3433,7 +3433,7 @@ msgstr ""
|
|||||||
msgid "invalid npipe source, source cannot be empty"
|
msgid "invalid npipe source, source cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:239
|
#: pkg/upstream/stack/stack.go:241
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid option %s for flag --resolve-image"
|
msgid "invalid option %s for flag --resolve-image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3456,7 +3456,7 @@ msgstr ""
|
|||||||
#. no spaces in between
|
#. no spaces in between
|
||||||
#. translators: `abra recipe lint` aliases. use a comma separated list of
|
#. translators: `abra recipe lint` aliases. use a comma separated list of
|
||||||
#. aliases with no spaces in between
|
#. aliases with no spaces in between
|
||||||
#: cli/app/cmd.go:261 cli/app/deploy.go:427 cli/app/logs.go:20
|
#: cli/app/cmd.go:261 cli/app/deploy.go:428 cli/app/logs.go:20
|
||||||
#: cli/recipe/lint.go:17 cli/server/add.go:207
|
#: cli/recipe/lint.go:17 cli/server/add.go:207
|
||||||
msgid "l"
|
msgid "l"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3472,7 +3472,7 @@ msgstr ""
|
|||||||
msgid "labels <domain> [flags]"
|
msgid "labels <domain> [flags]"
|
||||||
msgstr "etiquetas <domain> [flags]"
|
msgstr "etiquetas <domain> [flags]"
|
||||||
|
|
||||||
#: cli/app/deploy.go:426 cli/app/list.go:182
|
#: cli/app/deploy.go:427 cli/app/list.go:182
|
||||||
msgid "latest"
|
msgid "latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3562,12 +3562,12 @@ msgstr ""
|
|||||||
msgid "logs <domain> [service] [flags]"
|
msgid "logs <domain> [service] [flags]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:628
|
#: pkg/upstream/stack/stack.go:639
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "logs: %s"
|
msgid "logs: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:630
|
#: pkg/upstream/stack/stack.go:641
|
||||||
msgid "logs: no log output received from deployment"
|
msgid "logs: no log output received from deployment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3714,12 +3714,12 @@ msgstr ""
|
|||||||
msgid "need 3 or 4 arguments"
|
msgid "need 3 or 4 arguments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:348
|
#: pkg/upstream/stack/stack.go:352
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed, which you can do by running this on the server: docker network create -d overlay proxy"
|
msgid "network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed, which you can do by running this on the server: docker network create -d overlay proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:352
|
#: pkg/upstream/stack/stack.go:356
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\""
|
msgid "network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3942,11 +3942,11 @@ msgstr ""
|
|||||||
msgid "no volumes to remove"
|
msgid "no volumes to remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:418 cli/app/rollback.go:367 cli/app/upgrade.go:476
|
#: cli/app/deploy.go:419 cli/app/rollback.go:368 cli/app/upgrade.go:477
|
||||||
msgid "no-converge-checks"
|
msgid "no-converge-checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:410 cli/app/rollback.go:359 cli/app/upgrade.go:468
|
#: cli/app/deploy.go:411 cli/app/rollback.go:360 cli/app/upgrade.go:469
|
||||||
msgid "no-domain-checks"
|
msgid "no-domain-checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4002,7 +4002,7 @@ msgstr ""
|
|||||||
msgid "only show errors"
|
msgid "only show errors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:487
|
#: cli/app/upgrade.go:488
|
||||||
msgid "only show release notes"
|
msgid "only show release notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4036,22 +4036,22 @@ msgstr ""
|
|||||||
msgid "parsed following command arguments: %s"
|
msgid "parsed following command arguments: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:344
|
#: cli/app/upgrade.go:345
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing chosen upgrade version failed: %s"
|
msgid "parsing chosen upgrade version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:388
|
#: cli/app/upgrade.go:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing deployed version failed: %s"
|
msgid "parsing deployed version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:349
|
#: cli/app/upgrade.go:350
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing deployment version failed: %s"
|
msgid "parsing deployment version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:355 cli/app/upgrade.go:394
|
#: cli/app/upgrade.go:356 cli/app/upgrade.go:395
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "parsing recipe version failed: %s"
|
msgid "parsing recipe version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4079,8 +4079,8 @@ msgstr ""
|
|||||||
msgid "pattern"
|
msgid "pattern"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:405 cli/app/env.go:327 cli/app/remove.go:165
|
#: cli/app/deploy.go:406 cli/app/env.go:327 cli/app/remove.go:165
|
||||||
#: cli/app/rollback.go:354 cli/app/upgrade.go:463 cli/app/volume.go:219
|
#: cli/app/rollback.go:355 cli/app/upgrade.go:464 cli/app/volume.go:219
|
||||||
msgid "perform action without further prompt"
|
msgid "perform action without further prompt"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4095,27 +4095,27 @@ msgstr ""
|
|||||||
msgid "please fix your synced label for %s and re-run this command"
|
msgid "please fix your synced label for %s and re-run this command"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/rollback.go:266
|
#: cli/app/rollback.go:267
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select a downgrade (version: %s):"
|
msgid "please select a downgrade (version: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/rollback.go:271
|
#: cli/app/rollback.go:272
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select a downgrade (version: %s, chaos: %s):"
|
msgid "please select a downgrade (version: %s, chaos: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:311
|
#: cli/app/upgrade.go:312
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select an upgrade (version: %s):"
|
msgid "please select an upgrade (version: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/upgrade.go:316
|
#: cli/app/upgrade.go:317
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "please select an upgrade (version: %s, chaos: %s):"
|
msgid "please select an upgrade (version: %s, chaos: %s):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:576
|
#: pkg/upstream/stack/stack.go:587
|
||||||
msgid "polling deployment status"
|
msgid "polling deployment status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4206,7 +4206,7 @@ msgstr ""
|
|||||||
#. translators: `abra recipe` aliases. use a comma separated list of aliases
|
#. translators: `abra recipe` aliases. use a comma separated list of aliases
|
||||||
#. with no spaces in between
|
#. with no spaces in between
|
||||||
#: cli/app/backup.go:327 cli/app/list.go:300 cli/app/move.go:350
|
#: cli/app/backup.go:327 cli/app/list.go:300 cli/app/move.go:350
|
||||||
#: cli/app/run.go:23 cli/app/upgrade.go:485 cli/catalogue/catalogue.go:302
|
#: cli/app/run.go:23 cli/app/upgrade.go:486 cli/catalogue/catalogue.go:302
|
||||||
#: cli/recipe/recipe.go:12 cli/recipe/release.go:649 cli/recipe/sync.go:272
|
#: cli/recipe/recipe.go:12 cli/recipe/release.go:649 cli/recipe/sync.go:272
|
||||||
msgid "r"
|
msgid "r"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4325,7 +4325,7 @@ msgstr ""
|
|||||||
msgid "release <recipe> [version] [flags]"
|
msgid "release <recipe> [version] [flags]"
|
||||||
msgstr "publicar <recipe> [version] [flags]"
|
msgstr "publicar <recipe> [version] [flags]"
|
||||||
|
|
||||||
#: cli/app/upgrade.go:484
|
#: cli/app/upgrade.go:485
|
||||||
msgid "releasenotes"
|
msgid "releasenotes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4492,7 +4492,7 @@ msgstr ""
|
|||||||
msgid "restart <domain> [[service] | --all-services] [flags]"
|
msgid "restart <domain> [[service] | --all-services] [flags]"
|
||||||
msgstr "reiniciar <domain> [[service] | --all-services] [flags]"
|
msgstr "reiniciar <domain> [[service] | --all-services] [flags]"
|
||||||
|
|
||||||
#: cli/app/restart.go:171
|
#: cli/app/restart.go:172
|
||||||
msgid "restart all services"
|
msgid "restart all services"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4557,7 +4557,7 @@ msgstr ""
|
|||||||
msgid "retrieved versions from local recipe repository"
|
msgid "retrieved versions from local recipe repository"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:464
|
#: pkg/upstream/stack/stack.go:468
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "retrieving docker auth token: failed create docker cli: %s"
|
msgid "retrieving docker auth token: failed create docker cli: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4631,7 +4631,7 @@ msgstr ""
|
|||||||
msgid "run command locally"
|
msgid "run command locally"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:270 cli/app/upgrade.go:292
|
#: cli/app/deploy.go:271 cli/app/upgrade.go:293
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "run the following post-deploy commands: %s"
|
msgid "run the following post-deploy commands: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4720,12 +4720,12 @@ msgstr ""
|
|||||||
msgid "secret not found: %s"
|
msgid "secret not found: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:339
|
#: cli/app/deploy.go:340
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret not generated: %s"
|
msgid "secret not generated: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:337
|
#: cli/app/deploy.go:338
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret not inserted (#generate=false): %s"
|
msgid "secret not inserted (#generate=false): %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -4774,11 +4774,21 @@ msgstr ""
|
|||||||
msgid "server doesn't exist?"
|
msgid "server doesn't exist?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/client/client.go:48
|
#: pkg/client/client.go:54
|
||||||
|
#, c-format
|
||||||
|
msgid "server missing context, context creation failed: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: pkg/client/client.go:59
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "server missing context, run \"abra server add %s\"?"
|
msgid "server missing context, run \"abra server add %s\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: pkg/client/client.go:48
|
||||||
|
#, c-format
|
||||||
|
msgid "server missing, run \"abra server add %s\"?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: cli/server/add.go:148
|
#: cli/server/add.go:148
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup"
|
msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup"
|
||||||
@ -4851,7 +4861,7 @@ msgstr ""
|
|||||||
msgid "severity"
|
msgid "severity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:437 cli/app/rollback.go:378 cli/app/upgrade.go:495
|
#: cli/app/deploy.go:438 cli/app/rollback.go:379 cli/app/upgrade.go:496
|
||||||
msgid "show all configs & images, including unchanged ones"
|
msgid "show all configs & images, including unchanged ones"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4875,7 +4885,7 @@ msgstr ""
|
|||||||
msgid "show debug messages"
|
msgid "show debug messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:434 cli/app/rollback.go:375 cli/app/upgrade.go:492
|
#: cli/app/deploy.go:435 cli/app/rollback.go:376 cli/app/upgrade.go:493
|
||||||
msgid "show-unchanged"
|
msgid "show-unchanged"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4919,7 +4929,7 @@ msgstr ""
|
|||||||
msgid "skipping as requested, undeploy still in progress 🟠"
|
msgid "skipping as requested, undeploy still in progress 🟠"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:306
|
#: pkg/upstream/stack/stack.go:309
|
||||||
msgid "skipping converge logic checks"
|
msgid "skipping converge logic checks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4941,12 +4951,12 @@ msgstr ""
|
|||||||
msgid "skipping secret (because it already exists) on %s: %s"
|
msgid "skipping secret (because it already exists) on %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/app/app.go:692
|
#: pkg/app/app.go:697
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "skipping version %s write as already exists in %s.env"
|
msgid "skipping version %s write as already exists in %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/app/app.go:686
|
#: pkg/app/app.go:691
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "skipping writing version %s because dry run"
|
msgid "skipping writing version %s because dry run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5054,12 +5064,12 @@ msgstr ""
|
|||||||
msgid "successfully created %s"
|
msgid "successfully created %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/client/client.go:111
|
#: pkg/client/client.go:120
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "swarm mode not enabled on %s?"
|
msgid "swarm mode not enabled on %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/client/client.go:114
|
#: pkg/client/client.go:123
|
||||||
msgid "swarm mode not enabled on local server?"
|
msgid "swarm mode not enabled on local server?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5136,7 +5146,7 @@ msgstr ""
|
|||||||
msgid "timeout label: %s"
|
msgid "timeout label: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/remove.go:29 pkg/upstream/stack/stack.go:209
|
#: pkg/upstream/stack/remove.go:29 pkg/upstream/stack/stack.go:210
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "timeout: set to %d second(s)"
|
msgid "timeout: set to %d second(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5565,11 +5575,6 @@ msgstr ""
|
|||||||
msgid "unknown server %s, run \"abra server add %s\"?"
|
msgid "unknown server %s, run \"abra server add %s\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/client/client.go:51
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown server, run \"abra server add %s\"?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cli/app/cp.go:259
|
#: cli/app/cp.go:259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "untar: %s"
|
msgid "untar: %s"
|
||||||
@ -5581,7 +5586,7 @@ msgstr ""
|
|||||||
msgid "up"
|
msgid "up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:473
|
#: pkg/upstream/stack/stack.go:477
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "updating %s"
|
msgid "updating %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5694,7 +5699,7 @@ msgstr ""
|
|||||||
msgid "version"
|
msgid "version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/app/app.go:690
|
#: pkg/app/app.go:695
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version %s saved to %s.env"
|
msgid "version %s saved to %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5713,6 +5718,10 @@ msgstr ""
|
|||||||
msgid "version for abra"
|
msgid "version for abra"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: pkg/app/app.go:637
|
||||||
|
msgid "version is unknown, skipping env write"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/recipe/recipe.go:130
|
#: pkg/recipe/recipe.go:130
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version seems invalid: %s"
|
msgid "version seems invalid: %s"
|
||||||
@ -5723,27 +5732,27 @@ msgstr ""
|
|||||||
msgid "version wiped from %s.env"
|
msgid "version wiped from %s.env"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:353
|
#: cli/app/deploy.go:354
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking chaos version: %s"
|
msgid "version: taking chaos version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:379
|
#: cli/app/deploy.go:380
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking deployed version: %s"
|
msgid "version: taking deployed version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:384
|
#: cli/app/deploy.go:385
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking new recipe version: %s"
|
msgid "version: taking new recipe version: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:373
|
#: cli/app/deploy.go:374
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking version from .env file: %s"
|
msgid "version: taking version from .env file: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:359
|
#: cli/app/deploy.go:360
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "version: taking version from cli arg: %s"
|
msgid "version: taking version from cli arg: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5803,22 +5812,22 @@ msgstr ""
|
|||||||
msgid "volumes pruned: %d; space reclaimed: %s"
|
msgid "volumes pruned: %d; space reclaimed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:614
|
#: pkg/upstream/stack/stack.go:625
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error creating log dir: %s"
|
msgid "waitOnServices: error creating log dir: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:619
|
#: pkg/upstream/stack/stack.go:630
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error opening file: %s"
|
msgid "waitOnServices: error opening file: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:585
|
#: pkg/upstream/stack/stack.go:596
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: error running TUI: %s"
|
msgid "waitOnServices: error running TUI: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/upstream/stack/stack.go:625
|
#: pkg/upstream/stack/stack.go:636
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waitOnServices: writeFile: %s"
|
msgid "waitOnServices: writeFile: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5869,8 +5878,8 @@ msgstr ""
|
|||||||
msgid "writer: %v, "
|
msgid "writer: %v, "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cli/app/deploy.go:277 cli/app/new.go:241 cli/app/rollback.go:255
|
#: cli/app/deploy.go:278 cli/app/new.go:241 cli/app/rollback.go:256
|
||||||
#: cli/app/undeploy.go:120 cli/app/upgrade.go:300
|
#: cli/app/undeploy.go:120 cli/app/upgrade.go:301
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "writing recipe version failed: %s"
|
msgid "writing recipe version failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/ui"
|
"coopcloud.tech/abra/pkg/ui"
|
||||||
"coopcloud.tech/abra/pkg/upstream/convert"
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/stack/formatter"
|
"github.com/docker/cli/cli/command/formatter"
|
||||||
composetypes "github.com/docker/cli/cli/compose/types"
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
@ -201,6 +201,7 @@ func RunDeploy(
|
|||||||
appName string,
|
appName string,
|
||||||
serverName string,
|
serverName string,
|
||||||
dontWait bool,
|
dontWait bool,
|
||||||
|
noInput bool,
|
||||||
filters filters.Args,
|
filters filters.Args,
|
||||||
) error {
|
) error {
|
||||||
log.Info(i18n.G("initialising deployment"))
|
log.Info(i18n.G("initialising deployment"))
|
||||||
@ -226,6 +227,7 @@ func RunDeploy(
|
|||||||
appName,
|
appName,
|
||||||
serverName,
|
serverName,
|
||||||
dontWait,
|
dontWait,
|
||||||
|
noInput,
|
||||||
filters,
|
filters,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -248,6 +250,7 @@ func deployCompose(
|
|||||||
appName string,
|
appName string,
|
||||||
serverName string,
|
serverName string,
|
||||||
dontWait bool,
|
dontWait bool,
|
||||||
|
noInput bool,
|
||||||
filters filters.Args,
|
filters filters.Args,
|
||||||
) error {
|
) error {
|
||||||
namespace := convert.NewNamespace(opts.Namespace)
|
namespace := convert.NewNamespace(opts.Namespace)
|
||||||
@ -311,6 +314,7 @@ func deployCompose(
|
|||||||
Services: serviceIDs,
|
Services: serviceIDs,
|
||||||
AppName: appName,
|
AppName: appName,
|
||||||
ServerName: serverName,
|
ServerName: serverName,
|
||||||
|
NoInput: noInput,
|
||||||
Filters: filters,
|
Filters: filters,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,6 +565,7 @@ func timestamp() string {
|
|||||||
type WaitOpts struct {
|
type WaitOpts struct {
|
||||||
AppName string
|
AppName string
|
||||||
Filters filters.Args
|
Filters filters.Args
|
||||||
|
NoInput bool
|
||||||
NoLog bool
|
NoLog bool
|
||||||
Quiet bool
|
Quiet bool
|
||||||
ServerName string
|
ServerName string
|
||||||
@ -570,7 +575,13 @@ type WaitOpts struct {
|
|||||||
func WaitOnServices(ctx context.Context, cl *dockerClient.Client, opts WaitOpts) error {
|
func WaitOnServices(ctx context.Context, cl *dockerClient.Client, opts WaitOpts) error {
|
||||||
timeout := time.Duration(WaitTimeout) * time.Second
|
timeout := time.Duration(WaitTimeout) * time.Second
|
||||||
model := ui.DeployInitialModel(ctx, cl, opts.Services, opts.AppName, timeout, opts.Filters)
|
model := ui.DeployInitialModel(ctx, cl, opts.Services, opts.AppName, timeout, opts.Filters)
|
||||||
tui := tea.NewProgram(model)
|
|
||||||
|
var tui *tea.Program
|
||||||
|
if opts.NoInput {
|
||||||
|
tui = tea.NewProgram(model, tea.WithoutRenderer(), tea.WithInput(nil))
|
||||||
|
} else {
|
||||||
|
tui = tea.NewProgram(model)
|
||||||
|
}
|
||||||
|
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
log.Info(i18n.G("polling deployment status"))
|
log.Info(i18n.G("polling deployment status"))
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
ABRA_VERSION="0.11.0-beta"
|
ABRA_VERSION="0.12.0-beta"
|
||||||
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION"
|
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION"
|
||||||
RC_VERSION="0.11.0-beta"
|
RC_VERSION="0.12.0-beta"
|
||||||
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION"
|
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION"
|
||||||
|
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
@ -14,15 +14,15 @@ done
|
|||||||
|
|
||||||
function show_banner {
|
function show_banner {
|
||||||
echo ""
|
echo ""
|
||||||
echo " ____ ____ _ _ "
|
echo " ____ ____ _ _ "
|
||||||
echo " / ___|___ ___ _ __ / ___| | ___ _ _ __| |"
|
echo " / ___|___ ___ _ __ / ___| | ___ _ _ __| |"
|
||||||
echo " | | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |"
|
echo " | | / _ \ ___ / _ \| '_ \ | | | |/ _ \| | | |/ _' |"
|
||||||
echo " | |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |"
|
echo " | |__| (_) |___| (_) | |_) | | |___| | (_) | |_| | (_| |"
|
||||||
echo " \____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|"
|
echo " \____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|"
|
||||||
echo " |_|"
|
echo " |_|"
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
echo " === Public interest infrastructure === "
|
echo " === Public interest infrastructure === "
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -543,7 +543,7 @@ teardown(){
|
|||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "ignore timeout when not present in env" {
|
@test "ignore timeout when not present in env" {
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --debug
|
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks
|
||||||
assert_success
|
assert_success
|
||||||
refute_output --partial "timeout: set to"
|
refute_output --partial "timeout: set to"
|
||||||
}
|
}
|
||||||
@ -554,6 +554,7 @@ teardown(){
|
|||||||
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
|
# NOTE(d1}: --debug required
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --debug
|
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --debug
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial "timeout: set to 120"
|
assert_output --partial "timeout: set to 120"
|
||||||
@ -579,16 +580,25 @@ teardown(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "manually created server without context bails gracefully" {
|
@test "re-deploy updates existing env vars" {
|
||||||
run mkdir -p "$ABRA_DIR/servers/default2"
|
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input
|
||||||
assert_success
|
assert_success
|
||||||
assert_exists "$ABRA_DIR/servers/default2"
|
|
||||||
|
|
||||||
run cp "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" "$ABRA_DIR/servers/default2/$TEST_APP_DOMAIN_2.env"
|
run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \
|
||||||
|
$(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q)
|
||||||
assert_success
|
assert_success
|
||||||
assert_exists "$ABRA_DIR/servers/default2/$TEST_APP_DOMAIN_2.env"
|
assert_output --partial "WITH_COMMENT=foo"
|
||||||
|
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN_2" --no-input --no-converge-checks
|
run sed -i 's/WITH_COMMENT=foo/WITH_COMMENT=bar/g' \
|
||||||
assert_failure
|
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
||||||
assert_output --partial "server missing context"
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --force
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \
|
||||||
|
$(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q)
|
||||||
|
assert_success
|
||||||
|
refute_output --partial "WITH_COMMENT=foo"
|
||||||
|
assert_output --partial "WITH_COMMENT=bar"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,6 +68,13 @@ teardown(){
|
|||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "domain shown with https" {
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
|
--no-input --no-converge-checks
|
||||||
|
assert_success
|
||||||
|
assert_output --partial "https://$TEST_DOMAIN"
|
||||||
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "show changed config version on re-deploy" {
|
@test "show changed config version on re-deploy" {
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
|
|||||||
@ -160,23 +160,6 @@ teardown(){
|
|||||||
assert_not_exists "$ABRA_DIR/servers/foo.com"
|
assert_not_exists "$ABRA_DIR/servers/foo.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "list with status skips unknown servers" {
|
|
||||||
if [[ ! -d "$ABRA_DIR/servers/foo" ]]; then
|
|
||||||
run mkdir -p "$ABRA_DIR/servers/foo"
|
|
||||||
assert_success
|
|
||||||
assert_exists "$ABRA_DIR/servers/foo"
|
|
||||||
|
|
||||||
run cp "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" \
|
|
||||||
"$ABRA_DIR/servers/foo/$TEST_APP_DOMAIN.env"
|
|
||||||
assert_success
|
|
||||||
assert_exists "$ABRA_DIR/servers/foo/$TEST_APP_DOMAIN.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
run $ABRA app ls --status
|
|
||||||
assert_success
|
|
||||||
assert_output --partial "server missing context"
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "list does not fail if missing .env" {
|
@test "list does not fail if missing .env" {
|
||||||
_deploy_app
|
_deploy_app
|
||||||
|
|||||||
@ -19,6 +19,10 @@ setup(){
|
|||||||
teardown(){
|
teardown(){
|
||||||
_reset_recipe
|
_reset_recipe
|
||||||
_reset_tags
|
_reset_tags
|
||||||
|
if [[ -d "$ABRA_DIR/recipes/foobar" ]]; then
|
||||||
|
run rm -rf "$ABRA_DIR/recipes/foobar"
|
||||||
|
assert_success
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "validate recipe argument" {
|
@test "validate recipe argument" {
|
||||||
@ -126,3 +130,71 @@ teardown(){
|
|||||||
assert_line --index 0 --partial 'synced label'
|
assert_line --index 0 --partial 'synced label'
|
||||||
refute_line --index 1 --partial 'synced label'
|
refute_line --index 1 --partial 'synced label'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "sync with no tags or previous release" {
|
||||||
|
_remove_tags
|
||||||
|
|
||||||
|
run $ABRA recipe upgrade "$TEST_RECIPE" --no-input --patch
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" diff
|
||||||
|
assert_success
|
||||||
|
assert_output --partial 'image: nginx:1.21.6'
|
||||||
|
|
||||||
|
# NOTE(d1): ensure the latest tag is the one we expect
|
||||||
|
_remove_tags
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag \
|
||||||
|
-a "0.3.0+1.21.0" -m "fake: 0.3.0+1.21.0"
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA recipe sync "$TEST_RECIPE" --no-input --patch
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" diff
|
||||||
|
assert_success
|
||||||
|
assert_output --regexp 'coop-cloud\.\$\{STACK_NAME\}\.version=0\.3\.1\+1\.2.*'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "sync recipe without input fails with prompt" {
|
||||||
|
run $ABRA recipe new foobar
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||||
|
|
||||||
|
run $ABRA recipe sync foobar --no-input --patch
|
||||||
|
assert_failure
|
||||||
|
assert_output --partial "input required for initial version"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "sync new recipe: development release" {
|
||||||
|
run $ABRA recipe new foobar
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||||
|
|
||||||
|
run bash -c "echo 0.1.0 | $ABRA recipe sync foobar --patch"
|
||||||
|
assert_success
|
||||||
|
assert_output --regexp 'coop-cloud\.\$\{STACK_NAME\}\.version=0\.1\.0\+1\.2.*'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "sync new recipe: public release" {
|
||||||
|
run $ABRA recipe new foobar
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||||
|
|
||||||
|
run bash -c "echo 1.0.0 | $ABRA recipe sync foobar --patch"
|
||||||
|
assert_success
|
||||||
|
assert_output --regexp 'coop-cloud\.\$\{STACK_NAME\}\.version=1\.0\.0\+1\.2.*'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "sync newly created recipe with no version label" {
|
||||||
|
run $ABRA recipe new foobar
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||||
|
|
||||||
|
run sed -i 's/- "coop-cloud.${STACK_NAME}.version="/#- "coop-cloud.${STACK_NAME}.version="/g' \
|
||||||
|
"$ABRA_DIR/recipes/foobar/compose.yml"
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run bash -c "echo 0.1.0 | $ABRA recipe sync foobar --patch"
|
||||||
|
assert_failure
|
||||||
|
assert_output --partial "automagic insertion not supported yet"
|
||||||
|
}
|
||||||
|
|||||||
22
vendor/github.com/atotto/clipboard/.travis.yml
generated
vendored
22
vendor/github.com/atotto/clipboard/.travis.yml
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
- windows
|
|
||||||
|
|
||||||
go:
|
|
||||||
- go1.13.x
|
|
||||||
- go1.x
|
|
||||||
|
|
||||||
services:
|
|
||||||
- xvfb
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- export DISPLAY=:99.0
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xsel; fi
|
|
||||||
- go test -v .
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xclip; fi
|
|
||||||
- go test -v .
|
|
||||||
27
vendor/github.com/atotto/clipboard/LICENSE
generated
vendored
27
vendor/github.com/atotto/clipboard/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2013 Ato Araki. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of @atotto. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
48
vendor/github.com/atotto/clipboard/README.md
generated
vendored
48
vendor/github.com/atotto/clipboard/README.md
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
[](https://travis-ci.org/atotto/clipboard)
|
|
||||||
|
|
||||||
[](http://godoc.org/github.com/atotto/clipboard)
|
|
||||||
|
|
||||||
# Clipboard for Go
|
|
||||||
|
|
||||||
Provide copying and pasting to the Clipboard for Go.
|
|
||||||
|
|
||||||
Build:
|
|
||||||
|
|
||||||
$ go get github.com/atotto/clipboard
|
|
||||||
|
|
||||||
Platforms:
|
|
||||||
|
|
||||||
* OSX
|
|
||||||
* Windows 7 (probably work on other Windows)
|
|
||||||
* Linux, Unix (requires 'xclip' or 'xsel' command to be installed)
|
|
||||||
|
|
||||||
|
|
||||||
Document:
|
|
||||||
|
|
||||||
* http://godoc.org/github.com/atotto/clipboard
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
* Text string only
|
|
||||||
* UTF-8 text encoding only (no conversion)
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
|
|
||||||
* Clipboard watcher(?)
|
|
||||||
|
|
||||||
## Commands:
|
|
||||||
|
|
||||||
paste shell command:
|
|
||||||
|
|
||||||
$ go get github.com/atotto/clipboard/cmd/gopaste
|
|
||||||
$ # example:
|
|
||||||
$ gopaste > document.txt
|
|
||||||
|
|
||||||
copy shell command:
|
|
||||||
|
|
||||||
$ go get github.com/atotto/clipboard/cmd/gocopy
|
|
||||||
$ # example:
|
|
||||||
$ cat document.txt | gocopy
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
20
vendor/github.com/atotto/clipboard/clipboard.go
generated
vendored
20
vendor/github.com/atotto/clipboard/clipboard.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// Copyright 2013 @atotto. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package clipboard read/write on clipboard
|
|
||||||
package clipboard
|
|
||||||
|
|
||||||
// ReadAll read string from clipboard
|
|
||||||
func ReadAll() (string, error) {
|
|
||||||
return readAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteAll write string to clipboard
|
|
||||||
func WriteAll(text string) error {
|
|
||||||
return writeAll(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsupported might be set true during clipboard init, to help callers decide
|
|
||||||
// whether or not to offer clipboard options.
|
|
||||||
var Unsupported bool
|
|
||||||
52
vendor/github.com/atotto/clipboard/clipboard_darwin.go
generated
vendored
52
vendor/github.com/atotto/clipboard/clipboard_darwin.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2013 @atotto. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package clipboard
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
pasteCmdArgs = "pbpaste"
|
|
||||||
copyCmdArgs = "pbcopy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getPasteCommand() *exec.Cmd {
|
|
||||||
return exec.Command(pasteCmdArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCopyCommand() *exec.Cmd {
|
|
||||||
return exec.Command(copyCmdArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAll() (string, error) {
|
|
||||||
pasteCmd := getPasteCommand()
|
|
||||||
out, err := pasteCmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(out), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAll(text string) error {
|
|
||||||
copyCmd := getCopyCommand()
|
|
||||||
in, err := copyCmd.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := copyCmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := in.Write([]byte(text)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := in.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return copyCmd.Wait()
|
|
||||||
}
|
|
||||||
42
vendor/github.com/atotto/clipboard/clipboard_plan9.go
generated
vendored
42
vendor/github.com/atotto/clipboard/clipboard_plan9.go
generated
vendored
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2013 @atotto. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build plan9
|
|
||||||
|
|
||||||
package clipboard
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"io/ioutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func readAll() (string, error) {
|
|
||||||
f, err := os.Open("/dev/snarf")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
str, err := ioutil.ReadAll(f)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(str), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAll(text string) error {
|
|
||||||
f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = f.Write([]byte(text))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
149
vendor/github.com/atotto/clipboard/clipboard_unix.go
generated
vendored
149
vendor/github.com/atotto/clipboard/clipboard_unix.go
generated
vendored
@ -1,149 +0,0 @@
|
|||||||
// Copyright 2013 @atotto. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build freebsd linux netbsd openbsd solaris dragonfly
|
|
||||||
|
|
||||||
package clipboard
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
xsel = "xsel"
|
|
||||||
xclip = "xclip"
|
|
||||||
powershellExe = "powershell.exe"
|
|
||||||
clipExe = "clip.exe"
|
|
||||||
wlcopy = "wl-copy"
|
|
||||||
wlpaste = "wl-paste"
|
|
||||||
termuxClipboardGet = "termux-clipboard-get"
|
|
||||||
termuxClipboardSet = "termux-clipboard-set"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Primary bool
|
|
||||||
trimDos bool
|
|
||||||
|
|
||||||
pasteCmdArgs []string
|
|
||||||
copyCmdArgs []string
|
|
||||||
|
|
||||||
xselPasteArgs = []string{xsel, "--output", "--clipboard"}
|
|
||||||
xselCopyArgs = []string{xsel, "--input", "--clipboard"}
|
|
||||||
|
|
||||||
xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"}
|
|
||||||
xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"}
|
|
||||||
|
|
||||||
powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"}
|
|
||||||
clipExeCopyArgs = []string{clipExe}
|
|
||||||
|
|
||||||
wlpasteArgs = []string{wlpaste, "--no-newline"}
|
|
||||||
wlcopyArgs = []string{wlcopy}
|
|
||||||
|
|
||||||
termuxPasteArgs = []string{termuxClipboardGet}
|
|
||||||
termuxCopyArgs = []string{termuxClipboardSet}
|
|
||||||
|
|
||||||
missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.")
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if os.Getenv("WAYLAND_DISPLAY") != "" {
|
|
||||||
pasteCmdArgs = wlpasteArgs
|
|
||||||
copyCmdArgs = wlcopyArgs
|
|
||||||
|
|
||||||
if _, err := exec.LookPath(wlcopy); err == nil {
|
|
||||||
if _, err := exec.LookPath(wlpaste); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pasteCmdArgs = xclipPasteArgs
|
|
||||||
copyCmdArgs = xclipCopyArgs
|
|
||||||
|
|
||||||
if _, err := exec.LookPath(xclip); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pasteCmdArgs = xselPasteArgs
|
|
||||||
copyCmdArgs = xselCopyArgs
|
|
||||||
|
|
||||||
if _, err := exec.LookPath(xsel); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pasteCmdArgs = termuxPasteArgs
|
|
||||||
copyCmdArgs = termuxCopyArgs
|
|
||||||
|
|
||||||
if _, err := exec.LookPath(termuxClipboardSet); err == nil {
|
|
||||||
if _, err := exec.LookPath(termuxClipboardGet); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pasteCmdArgs = powershellExePasteArgs
|
|
||||||
copyCmdArgs = clipExeCopyArgs
|
|
||||||
trimDos = true
|
|
||||||
|
|
||||||
if _, err := exec.LookPath(clipExe); err == nil {
|
|
||||||
if _, err := exec.LookPath(powershellExe); err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Unsupported = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPasteCommand() *exec.Cmd {
|
|
||||||
if Primary {
|
|
||||||
pasteCmdArgs = pasteCmdArgs[:1]
|
|
||||||
}
|
|
||||||
return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCopyCommand() *exec.Cmd {
|
|
||||||
if Primary {
|
|
||||||
copyCmdArgs = copyCmdArgs[:1]
|
|
||||||
}
|
|
||||||
return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAll() (string, error) {
|
|
||||||
if Unsupported {
|
|
||||||
return "", missingCommands
|
|
||||||
}
|
|
||||||
pasteCmd := getPasteCommand()
|
|
||||||
out, err := pasteCmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
result := string(out)
|
|
||||||
if trimDos && len(result) > 1 {
|
|
||||||
result = result[:len(result)-2]
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAll(text string) error {
|
|
||||||
if Unsupported {
|
|
||||||
return missingCommands
|
|
||||||
}
|
|
||||||
copyCmd := getCopyCommand()
|
|
||||||
in, err := copyCmd.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := copyCmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := in.Write([]byte(text)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := in.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return copyCmd.Wait()
|
|
||||||
}
|
|
||||||
157
vendor/github.com/atotto/clipboard/clipboard_windows.go
generated
vendored
157
vendor/github.com/atotto/clipboard/clipboard_windows.go
generated
vendored
@ -1,157 +0,0 @@
|
|||||||
// Copyright 2013 @atotto. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package clipboard
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
cfUnicodetext = 13
|
|
||||||
gmemMoveable = 0x0002
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
user32 = syscall.MustLoadDLL("user32")
|
|
||||||
isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable")
|
|
||||||
openClipboard = user32.MustFindProc("OpenClipboard")
|
|
||||||
closeClipboard = user32.MustFindProc("CloseClipboard")
|
|
||||||
emptyClipboard = user32.MustFindProc("EmptyClipboard")
|
|
||||||
getClipboardData = user32.MustFindProc("GetClipboardData")
|
|
||||||
setClipboardData = user32.MustFindProc("SetClipboardData")
|
|
||||||
|
|
||||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
|
||||||
globalAlloc = kernel32.NewProc("GlobalAlloc")
|
|
||||||
globalFree = kernel32.NewProc("GlobalFree")
|
|
||||||
globalLock = kernel32.NewProc("GlobalLock")
|
|
||||||
globalUnlock = kernel32.NewProc("GlobalUnlock")
|
|
||||||
lstrcpy = kernel32.NewProc("lstrcpyW")
|
|
||||||
)
|
|
||||||
|
|
||||||
// waitOpenClipboard opens the clipboard, waiting for up to a second to do so.
|
|
||||||
func waitOpenClipboard() error {
|
|
||||||
started := time.Now()
|
|
||||||
limit := started.Add(time.Second)
|
|
||||||
var r uintptr
|
|
||||||
var err error
|
|
||||||
for time.Now().Before(limit) {
|
|
||||||
r, _, err = openClipboard.Call(0)
|
|
||||||
if r != 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAll() (string, error) {
|
|
||||||
// LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution).
|
|
||||||
// Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock.
|
|
||||||
runtime.LockOSThread()
|
|
||||||
defer runtime.UnlockOSThread()
|
|
||||||
if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
err := waitOpenClipboard()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
h, _, err := getClipboardData.Call(cfUnicodetext)
|
|
||||||
if h == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
l, _, err := globalLock.Call(h)
|
|
||||||
if l == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:])
|
|
||||||
|
|
||||||
r, _, err := globalUnlock.Call(h)
|
|
||||||
if r == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
closed, _, err := closeClipboard.Call()
|
|
||||||
if closed == 0 {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return text, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAll(text string) error {
|
|
||||||
// LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution).
|
|
||||||
// Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock.
|
|
||||||
runtime.LockOSThread()
|
|
||||||
defer runtime.UnlockOSThread()
|
|
||||||
|
|
||||||
err := waitOpenClipboard()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _, err := emptyClipboard.Call(0)
|
|
||||||
if r == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
data := syscall.StringToUTF16(text)
|
|
||||||
|
|
||||||
// "If the hMem parameter identifies a memory object, the object must have
|
|
||||||
// been allocated using the function with the GMEM_MOVEABLE flag."
|
|
||||||
h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0]))))
|
|
||||||
if h == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if h != 0 {
|
|
||||||
globalFree.Call(h)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
l, _, err := globalLock.Call(h)
|
|
||||||
if l == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0])))
|
|
||||||
if r == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _, err = globalUnlock.Call(h)
|
|
||||||
if r == 0 {
|
|
||||||
if err.(syscall.Errno) != 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _, err = setClipboardData.Call(cfUnicodetext, h)
|
|
||||||
if r == 0 {
|
|
||||||
_, _, _ = closeClipboard.Call()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h = 0 // suppress deferred cleanup
|
|
||||||
closed, _, err := closeClipboard.Call()
|
|
||||||
if closed == 0 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
21
vendor/github.com/charmbracelet/bubbles/LICENSE
generated
vendored
21
vendor/github.com/charmbracelet/bubbles/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020-2023 Charmbracelet, Inc
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
219
vendor/github.com/charmbracelet/bubbles/cursor/cursor.go
generated
vendored
219
vendor/github.com/charmbracelet/bubbles/cursor/cursor.go
generated
vendored
@ -1,219 +0,0 @@
|
|||||||
// Package cursor provides cursor functionality for Bubble Tea applications.
|
|
||||||
package cursor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
|
||||||
"github.com/charmbracelet/lipgloss"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultBlinkSpeed = time.Millisecond * 530
|
|
||||||
|
|
||||||
// initialBlinkMsg initializes cursor blinking.
|
|
||||||
type initialBlinkMsg struct{}
|
|
||||||
|
|
||||||
// BlinkMsg signals that the cursor should blink. It contains metadata that
|
|
||||||
// allows us to tell if the blink message is the one we're expecting.
|
|
||||||
type BlinkMsg struct {
|
|
||||||
id int
|
|
||||||
tag int
|
|
||||||
}
|
|
||||||
|
|
||||||
// blinkCanceled is sent when a blink operation is canceled.
|
|
||||||
type blinkCanceled struct{}
|
|
||||||
|
|
||||||
// blinkCtx manages cursor blinking.
|
|
||||||
type blinkCtx struct {
|
|
||||||
ctx context.Context
|
|
||||||
cancel context.CancelFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode describes the behavior of the cursor.
|
|
||||||
type Mode int
|
|
||||||
|
|
||||||
// Available cursor modes.
|
|
||||||
const (
|
|
||||||
CursorBlink Mode = iota
|
|
||||||
CursorStatic
|
|
||||||
CursorHide
|
|
||||||
)
|
|
||||||
|
|
||||||
// String returns the cursor mode in a human-readable format. This method is
|
|
||||||
// provisional and for informational purposes only.
|
|
||||||
func (c Mode) String() string {
|
|
||||||
return [...]string{
|
|
||||||
"blink",
|
|
||||||
"static",
|
|
||||||
"hidden",
|
|
||||||
}[c]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model is the Bubble Tea model for this cursor element.
|
|
||||||
type Model struct {
|
|
||||||
BlinkSpeed time.Duration
|
|
||||||
// Style for styling the cursor block.
|
|
||||||
Style lipgloss.Style
|
|
||||||
// TextStyle is the style used for the cursor when it is hidden (when blinking).
|
|
||||||
// I.e. displaying normal text.
|
|
||||||
TextStyle lipgloss.Style
|
|
||||||
|
|
||||||
// char is the character under the cursor
|
|
||||||
char string
|
|
||||||
// The ID of this Model as it relates to other cursors
|
|
||||||
id int
|
|
||||||
// focus indicates whether the containing input is focused
|
|
||||||
focus bool
|
|
||||||
// Cursor Blink state.
|
|
||||||
Blink bool
|
|
||||||
// Used to manage cursor blink
|
|
||||||
blinkCtx *blinkCtx
|
|
||||||
// The ID of the blink message we're expecting to receive.
|
|
||||||
blinkTag int
|
|
||||||
// mode determines the behavior of the cursor
|
|
||||||
mode Mode
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new model with default settings.
|
|
||||||
func New() Model {
|
|
||||||
return Model{
|
|
||||||
BlinkSpeed: defaultBlinkSpeed,
|
|
||||||
|
|
||||||
Blink: true,
|
|
||||||
mode: CursorBlink,
|
|
||||||
|
|
||||||
blinkCtx: &blinkCtx{
|
|
||||||
ctx: context.Background(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates the cursor.
|
|
||||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|
||||||
switch msg := msg.(type) {
|
|
||||||
case initialBlinkMsg:
|
|
||||||
// We accept all initialBlinkMsgs generated by the Blink command.
|
|
||||||
|
|
||||||
if m.mode != CursorBlink || !m.focus {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := m.BlinkCmd()
|
|
||||||
return m, cmd
|
|
||||||
|
|
||||||
case tea.FocusMsg:
|
|
||||||
return m, m.Focus()
|
|
||||||
|
|
||||||
case tea.BlurMsg:
|
|
||||||
m.Blur()
|
|
||||||
return m, nil
|
|
||||||
|
|
||||||
case BlinkMsg:
|
|
||||||
// We're choosy about whether to accept blinkMsgs so that our cursor
|
|
||||||
// only exactly when it should.
|
|
||||||
|
|
||||||
// Is this model blink-able?
|
|
||||||
if m.mode != CursorBlink || !m.focus {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Were we expecting this blink message?
|
|
||||||
if msg.id != m.id || msg.tag != m.blinkTag {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var cmd tea.Cmd
|
|
||||||
if m.mode == CursorBlink {
|
|
||||||
m.Blink = !m.Blink
|
|
||||||
cmd = m.BlinkCmd()
|
|
||||||
}
|
|
||||||
return m, cmd
|
|
||||||
|
|
||||||
case blinkCanceled: // no-op
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode returns the model's cursor mode. For available cursor modes, see
|
|
||||||
// type Mode.
|
|
||||||
func (m Model) Mode() Mode {
|
|
||||||
return m.mode
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMode sets the model's cursor mode. This method returns a command.
|
|
||||||
//
|
|
||||||
// For available cursor modes, see type CursorMode.
|
|
||||||
func (m *Model) SetMode(mode Mode) tea.Cmd {
|
|
||||||
// Adjust the mode value if it's value is out of range
|
|
||||||
if mode < CursorBlink || mode > CursorHide {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
m.mode = mode
|
|
||||||
m.Blink = m.mode == CursorHide || !m.focus
|
|
||||||
if mode == CursorBlink {
|
|
||||||
return Blink
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlinkCmd is a command used to manage cursor blinking.
|
|
||||||
func (m *Model) BlinkCmd() tea.Cmd {
|
|
||||||
if m.mode != CursorBlink {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.blinkCtx != nil && m.blinkCtx.cancel != nil {
|
|
||||||
m.blinkCtx.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(m.blinkCtx.ctx, m.BlinkSpeed)
|
|
||||||
m.blinkCtx.cancel = cancel
|
|
||||||
|
|
||||||
m.blinkTag++
|
|
||||||
|
|
||||||
return func() tea.Msg {
|
|
||||||
defer cancel()
|
|
||||||
<-ctx.Done()
|
|
||||||
if ctx.Err() == context.DeadlineExceeded {
|
|
||||||
return BlinkMsg{id: m.id, tag: m.blinkTag}
|
|
||||||
}
|
|
||||||
return blinkCanceled{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blink is a command used to initialize cursor blinking.
|
|
||||||
func Blink() tea.Msg {
|
|
||||||
return initialBlinkMsg{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus focuses the cursor to allow it to blink if desired.
|
|
||||||
func (m *Model) Focus() tea.Cmd {
|
|
||||||
m.focus = true
|
|
||||||
m.Blink = m.mode == CursorHide // show the cursor unless we've explicitly hidden it
|
|
||||||
|
|
||||||
if m.mode == CursorBlink && m.focus {
|
|
||||||
return m.BlinkCmd()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blur blurs the cursor.
|
|
||||||
func (m *Model) Blur() {
|
|
||||||
m.focus = false
|
|
||||||
m.Blink = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetChar sets the character under the cursor.
|
|
||||||
func (m *Model) SetChar(char string) {
|
|
||||||
m.char = char
|
|
||||||
}
|
|
||||||
|
|
||||||
// View displays the cursor.
|
|
||||||
func (m Model) View() string {
|
|
||||||
if m.Blink {
|
|
||||||
return m.TextStyle.Inline(true).Render(m.char)
|
|
||||||
}
|
|
||||||
return m.Style.Inline(true).Reverse(true).Render(m.char)
|
|
||||||
}
|
|
||||||
140
vendor/github.com/charmbracelet/bubbles/key/key.go
generated
vendored
140
vendor/github.com/charmbracelet/bubbles/key/key.go
generated
vendored
@ -1,140 +0,0 @@
|
|||||||
// Package key provides some types and functions for generating user-definable
|
|
||||||
// keymappings useful in Bubble Tea components. There are a few different ways
|
|
||||||
// you can define a keymapping with this package. Here's one example:
|
|
||||||
//
|
|
||||||
// type KeyMap struct {
|
|
||||||
// Up key.Binding
|
|
||||||
// Down key.Binding
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var DefaultKeyMap = KeyMap{
|
|
||||||
// Up: key.NewBinding(
|
|
||||||
// key.WithKeys("k", "up"), // actual keybindings
|
|
||||||
// key.WithHelp("↑/k", "move up"), // corresponding help text
|
|
||||||
// ),
|
|
||||||
// Down: key.NewBinding(
|
|
||||||
// key.WithKeys("j", "down"),
|
|
||||||
// key.WithHelp("↓/j", "move down"),
|
|
||||||
// ),
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
||||||
// switch msg := msg.(type) {
|
|
||||||
// case tea.KeyMsg:
|
|
||||||
// switch {
|
|
||||||
// case key.Matches(msg, DefaultKeyMap.Up):
|
|
||||||
// // The user pressed up
|
|
||||||
// case key.Matches(msg, DefaultKeyMap.Down):
|
|
||||||
// // The user pressed down
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The help information, which is not used in the example above, can be used
|
|
||||||
// to render help text for keystrokes in your views.
|
|
||||||
package key
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Binding describes a set of keybindings and, optionally, their associated
|
|
||||||
// help text.
|
|
||||||
type Binding struct {
|
|
||||||
keys []string
|
|
||||||
help Help
|
|
||||||
disabled bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindingOpt is an initialization option for a keybinding. It's used as an
|
|
||||||
// argument to NewBinding.
|
|
||||||
type BindingOpt func(*Binding)
|
|
||||||
|
|
||||||
// NewBinding returns a new keybinding from a set of BindingOpt options.
|
|
||||||
func NewBinding(opts ...BindingOpt) Binding {
|
|
||||||
b := &Binding{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(b)
|
|
||||||
}
|
|
||||||
return *b
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithKeys initializes a keybinding with the given keystrokes.
|
|
||||||
func WithKeys(keys ...string) BindingOpt {
|
|
||||||
return func(b *Binding) {
|
|
||||||
b.keys = keys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHelp initializes a keybinding with the given help text.
|
|
||||||
func WithHelp(key, desc string) BindingOpt {
|
|
||||||
return func(b *Binding) {
|
|
||||||
b.help = Help{Key: key, Desc: desc}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDisabled initializes a disabled keybinding.
|
|
||||||
func WithDisabled() BindingOpt {
|
|
||||||
return func(b *Binding) {
|
|
||||||
b.disabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKeys sets the keys for the keybinding.
|
|
||||||
func (b *Binding) SetKeys(keys ...string) {
|
|
||||||
b.keys = keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns the keys for the keybinding.
|
|
||||||
func (b Binding) Keys() []string {
|
|
||||||
return b.keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHelp sets the help text for the keybinding.
|
|
||||||
func (b *Binding) SetHelp(key, desc string) {
|
|
||||||
b.help = Help{Key: key, Desc: desc}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Help returns the Help information for the keybinding.
|
|
||||||
func (b Binding) Help() Help {
|
|
||||||
return b.help
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enabled returns whether or not the keybinding is enabled. Disabled
|
|
||||||
// keybindings won't be activated and won't show up in help. Keybindings are
|
|
||||||
// enabled by default.
|
|
||||||
func (b Binding) Enabled() bool {
|
|
||||||
return !b.disabled && b.keys != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetEnabled enables or disables the keybinding.
|
|
||||||
func (b *Binding) SetEnabled(v bool) {
|
|
||||||
b.disabled = !v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unbind removes the keys and help from this binding, effectively nullifying
|
|
||||||
// it. This is a step beyond disabling it, since applications can enable
|
|
||||||
// or disable key bindings based on application state.
|
|
||||||
func (b *Binding) Unbind() {
|
|
||||||
b.keys = nil
|
|
||||||
b.help = Help{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Help is help information for a given keybinding.
|
|
||||||
type Help struct {
|
|
||||||
Key string
|
|
||||||
Desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matches checks if the given key matches the given bindings.
|
|
||||||
func Matches[Key fmt.Stringer](k Key, b ...Binding) bool {
|
|
||||||
keys := k.String()
|
|
||||||
for _, binding := range b {
|
|
||||||
for _, v := range binding.keys {
|
|
||||||
if keys == v && binding.Enabled() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
102
vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go
generated
vendored
102
vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
// Package runeutil provides a utility function for use in Bubbles
|
|
||||||
// that can process Key messages containing runes.
|
|
||||||
package runeutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sanitizer is a helper for bubble widgets that want to process
|
|
||||||
// Runes from input key messages.
|
|
||||||
type Sanitizer interface {
|
|
||||||
// Sanitize removes control characters from runes in a KeyRunes
|
|
||||||
// message, and optionally replaces newline/carriage return/tabs by a
|
|
||||||
// specified character.
|
|
||||||
//
|
|
||||||
// The rune array is modified in-place if possible. In that case, the
|
|
||||||
// returned slice is the original slice shortened after the control
|
|
||||||
// characters have been removed/translated.
|
|
||||||
Sanitize(runes []rune) []rune
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSanitizer constructs a rune sanitizer.
|
|
||||||
func NewSanitizer(opts ...Option) Sanitizer {
|
|
||||||
s := sanitizer{
|
|
||||||
replaceNewLine: []rune("\n"),
|
|
||||||
replaceTab: []rune(" "),
|
|
||||||
}
|
|
||||||
for _, o := range opts {
|
|
||||||
s = o(s)
|
|
||||||
}
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option is the type of option that can be passed to Sanitize().
|
|
||||||
type Option func(sanitizer) sanitizer
|
|
||||||
|
|
||||||
// ReplaceTabs replaces tabs by the specified string.
|
|
||||||
func ReplaceTabs(tabRepl string) Option {
|
|
||||||
return func(s sanitizer) sanitizer {
|
|
||||||
s.replaceTab = []rune(tabRepl)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplaceNewlines replaces newline characters by the specified string.
|
|
||||||
func ReplaceNewlines(nlRepl string) Option {
|
|
||||||
return func(s sanitizer) sanitizer {
|
|
||||||
s.replaceNewLine = []rune(nlRepl)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sanitizer) Sanitize(runes []rune) []rune {
|
|
||||||
// dstrunes are where we are storing the result.
|
|
||||||
dstrunes := runes[:0:len(runes)]
|
|
||||||
// copied indicates whether dstrunes is an alias of runes
|
|
||||||
// or a copy. We need a copy when dst moves past src.
|
|
||||||
// We use this as an optimization to avoid allocating
|
|
||||||
// a new rune slice in the common case where the output
|
|
||||||
// is smaller or equal to the input.
|
|
||||||
copied := false
|
|
||||||
|
|
||||||
for src := 0; src < len(runes); src++ {
|
|
||||||
r := runes[src]
|
|
||||||
switch {
|
|
||||||
case r == utf8.RuneError:
|
|
||||||
// skip
|
|
||||||
|
|
||||||
case r == '\r' || r == '\n':
|
|
||||||
if len(dstrunes)+len(s.replaceNewLine) > src && !copied {
|
|
||||||
dst := len(dstrunes)
|
|
||||||
dstrunes = make([]rune, dst, len(runes)+len(s.replaceNewLine))
|
|
||||||
copy(dstrunes, runes[:dst])
|
|
||||||
copied = true
|
|
||||||
}
|
|
||||||
dstrunes = append(dstrunes, s.replaceNewLine...)
|
|
||||||
|
|
||||||
case r == '\t':
|
|
||||||
if len(dstrunes)+len(s.replaceTab) > src && !copied {
|
|
||||||
dst := len(dstrunes)
|
|
||||||
dstrunes = make([]rune, dst, len(runes)+len(s.replaceTab))
|
|
||||||
copy(dstrunes, runes[:dst])
|
|
||||||
copied = true
|
|
||||||
}
|
|
||||||
dstrunes = append(dstrunes, s.replaceTab...)
|
|
||||||
|
|
||||||
case unicode.IsControl(r):
|
|
||||||
// Other control characters: skip.
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Keep the character.
|
|
||||||
dstrunes = append(dstrunes, runes[src])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dstrunes
|
|
||||||
}
|
|
||||||
|
|
||||||
type sanitizer struct {
|
|
||||||
replaceNewLine []rune
|
|
||||||
replaceTab []rune
|
|
||||||
}
|
|
||||||
224
vendor/github.com/charmbracelet/bubbles/spinner/spinner.go
generated
vendored
224
vendor/github.com/charmbracelet/bubbles/spinner/spinner.go
generated
vendored
@ -1,224 +0,0 @@
|
|||||||
// Package spinner provides a spinner component for Bubble Tea applications.
|
|
||||||
package spinner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
|
||||||
"github.com/charmbracelet/lipgloss"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Internal ID management. Used during animating to ensure that frame messages
|
|
||||||
// are received only by spinner components that sent them.
|
|
||||||
var lastID int64
|
|
||||||
|
|
||||||
func nextID() int {
|
|
||||||
return int(atomic.AddInt64(&lastID, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spinner is a set of frames used in animating the spinner.
|
|
||||||
type Spinner struct {
|
|
||||||
Frames []string
|
|
||||||
FPS time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some spinners to choose from. You could also make your own.
|
|
||||||
var (
|
|
||||||
Line = Spinner{
|
|
||||||
Frames: []string{"|", "/", "-", "\\"},
|
|
||||||
FPS: time.Second / 10, //nolint:mnd
|
|
||||||
}
|
|
||||||
Dot = Spinner{
|
|
||||||
Frames: []string{"⣾ ", "⣽ ", "⣻ ", "⢿ ", "⡿ ", "⣟ ", "⣯ ", "⣷ "},
|
|
||||||
FPS: time.Second / 10, //nolint:mnd
|
|
||||||
}
|
|
||||||
MiniDot = Spinner{
|
|
||||||
Frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
|
|
||||||
FPS: time.Second / 12, //nolint:mnd
|
|
||||||
}
|
|
||||||
Jump = Spinner{
|
|
||||||
Frames: []string{"⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"},
|
|
||||||
FPS: time.Second / 10, //nolint:mnd
|
|
||||||
}
|
|
||||||
Pulse = Spinner{
|
|
||||||
Frames: []string{"█", "▓", "▒", "░"},
|
|
||||||
FPS: time.Second / 8, //nolint:mnd
|
|
||||||
}
|
|
||||||
Points = Spinner{
|
|
||||||
Frames: []string{"∙∙∙", "●∙∙", "∙●∙", "∙∙●"},
|
|
||||||
FPS: time.Second / 7, //nolint:mnd
|
|
||||||
}
|
|
||||||
Globe = Spinner{
|
|
||||||
Frames: []string{"🌍", "🌎", "🌏"},
|
|
||||||
FPS: time.Second / 4, //nolint:mnd
|
|
||||||
}
|
|
||||||
Moon = Spinner{
|
|
||||||
Frames: []string{"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"},
|
|
||||||
FPS: time.Second / 8, //nolint:mnd
|
|
||||||
}
|
|
||||||
Monkey = Spinner{
|
|
||||||
Frames: []string{"🙈", "🙉", "🙊"},
|
|
||||||
FPS: time.Second / 3, //nolint:mnd
|
|
||||||
}
|
|
||||||
Meter = Spinner{
|
|
||||||
Frames: []string{
|
|
||||||
"▱▱▱",
|
|
||||||
"▰▱▱",
|
|
||||||
"▰▰▱",
|
|
||||||
"▰▰▰",
|
|
||||||
"▰▰▱",
|
|
||||||
"▰▱▱",
|
|
||||||
"▱▱▱",
|
|
||||||
},
|
|
||||||
FPS: time.Second / 7, //nolint:mnd
|
|
||||||
}
|
|
||||||
Hamburger = Spinner{
|
|
||||||
Frames: []string{"☱", "☲", "☴", "☲"},
|
|
||||||
FPS: time.Second / 3, //nolint:mnd
|
|
||||||
}
|
|
||||||
Ellipsis = Spinner{
|
|
||||||
Frames: []string{"", ".", "..", "..."},
|
|
||||||
FPS: time.Second / 3, //nolint:mnd
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model contains the state for the spinner. Use New to create new models
|
|
||||||
// rather than using Model as a struct literal.
|
|
||||||
type Model struct {
|
|
||||||
// Spinner settings to use. See type Spinner.
|
|
||||||
Spinner Spinner
|
|
||||||
|
|
||||||
// Style sets the styling for the spinner. Most of the time you'll just
|
|
||||||
// want foreground and background coloring, and potentially some padding.
|
|
||||||
//
|
|
||||||
// For an introduction to styling with Lip Gloss see:
|
|
||||||
// https://github.com/charmbracelet/lipgloss
|
|
||||||
Style lipgloss.Style
|
|
||||||
|
|
||||||
frame int
|
|
||||||
id int
|
|
||||||
tag int
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns the spinner's unique ID.
|
|
||||||
func (m Model) ID() int {
|
|
||||||
return m.id
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a model with default values.
|
|
||||||
func New(opts ...Option) Model {
|
|
||||||
m := Model{
|
|
||||||
Spinner: Line,
|
|
||||||
id: nextID(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewModel returns a model with default values.
|
|
||||||
//
|
|
||||||
// Deprecated: use [New] instead.
|
|
||||||
var NewModel = New
|
|
||||||
|
|
||||||
// TickMsg indicates that the timer has ticked and we should render a frame.
|
|
||||||
type TickMsg struct {
|
|
||||||
Time time.Time
|
|
||||||
tag int
|
|
||||||
ID int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is the Tea update function.
|
|
||||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|
||||||
switch msg := msg.(type) {
|
|
||||||
case TickMsg:
|
|
||||||
// If an ID is set, and the ID doesn't belong to this spinner, reject
|
|
||||||
// the message.
|
|
||||||
if msg.ID > 0 && msg.ID != m.id {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a tag is set, and it's not the one we expect, reject the message.
|
|
||||||
// This prevents the spinner from receiving too many messages and
|
|
||||||
// thus spinning too fast.
|
|
||||||
if msg.tag > 0 && msg.tag != m.tag {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.frame++
|
|
||||||
if m.frame >= len(m.Spinner.Frames) {
|
|
||||||
m.frame = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
m.tag++
|
|
||||||
return m, m.tick(m.id, m.tag)
|
|
||||||
default:
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// View renders the model's view.
|
|
||||||
func (m Model) View() string {
|
|
||||||
if m.frame >= len(m.Spinner.Frames) {
|
|
||||||
return "(error)"
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Style.Render(m.Spinner.Frames[m.frame])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tick is the command used to advance the spinner one frame. Use this command
|
|
||||||
// to effectively start the spinner.
|
|
||||||
func (m Model) Tick() tea.Msg {
|
|
||||||
return TickMsg{
|
|
||||||
// The time at which the tick occurred.
|
|
||||||
Time: time.Now(),
|
|
||||||
|
|
||||||
// The ID of the spinner that this message belongs to. This can be
|
|
||||||
// helpful when routing messages, however bear in mind that spinners
|
|
||||||
// will ignore messages that don't contain ID by default.
|
|
||||||
ID: m.id,
|
|
||||||
|
|
||||||
tag: m.tag,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Model) tick(id, tag int) tea.Cmd {
|
|
||||||
return tea.Tick(m.Spinner.FPS, func(t time.Time) tea.Msg {
|
|
||||||
return TickMsg{
|
|
||||||
Time: t,
|
|
||||||
ID: id,
|
|
||||||
tag: tag,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tick is the command used to advance the spinner one frame. Use this command
|
|
||||||
// to effectively start the spinner.
|
|
||||||
//
|
|
||||||
// Deprecated: Use [Model.Tick] instead.
|
|
||||||
func Tick() tea.Msg {
|
|
||||||
return TickMsg{Time: time.Now()}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option is used to set options in New. For example:
|
|
||||||
//
|
|
||||||
// spinner := New(WithSpinner(Dot))
|
|
||||||
type Option func(*Model)
|
|
||||||
|
|
||||||
// WithSpinner is an option to set the spinner.
|
|
||||||
func WithSpinner(spinner Spinner) Option {
|
|
||||||
return func(m *Model) {
|
|
||||||
m.Spinner = spinner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithStyle is an option to set the spinner style.
|
|
||||||
func WithStyle(style lipgloss.Style) Option {
|
|
||||||
return func(m *Model) {
|
|
||||||
m.Style = style
|
|
||||||
}
|
|
||||||
}
|
|
||||||
898
vendor/github.com/charmbracelet/bubbles/textinput/textinput.go
generated
vendored
898
vendor/github.com/charmbracelet/bubbles/textinput/textinput.go
generated
vendored
@ -1,898 +0,0 @@
|
|||||||
// Package textinput provides a text input component for Bubble Tea
|
|
||||||
// applications.
|
|
||||||
package textinput
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/atotto/clipboard"
|
|
||||||
"github.com/charmbracelet/bubbles/cursor"
|
|
||||||
"github.com/charmbracelet/bubbles/key"
|
|
||||||
"github.com/charmbracelet/bubbles/runeutil"
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
|
||||||
"github.com/charmbracelet/lipgloss"
|
|
||||||
rw "github.com/mattn/go-runewidth"
|
|
||||||
"github.com/rivo/uniseg"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Internal messages for clipboard operations.
|
|
||||||
type (
|
|
||||||
pasteMsg string
|
|
||||||
pasteErrMsg struct{ error }
|
|
||||||
)
|
|
||||||
|
|
||||||
// EchoMode sets the input behavior of the text input field.
|
|
||||||
type EchoMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// EchoNormal displays text as is. This is the default behavior.
|
|
||||||
EchoNormal EchoMode = iota
|
|
||||||
|
|
||||||
// EchoPassword displays the EchoCharacter mask instead of actual
|
|
||||||
// characters. This is commonly used for password fields.
|
|
||||||
EchoPassword
|
|
||||||
|
|
||||||
// EchoNone displays nothing as characters are entered. This is commonly
|
|
||||||
// seen for password fields on the command line.
|
|
||||||
EchoNone
|
|
||||||
)
|
|
||||||
|
|
||||||
// ValidateFunc is a function that returns an error if the input is invalid.
|
|
||||||
type ValidateFunc func(string) error
|
|
||||||
|
|
||||||
// KeyMap is the key bindings for different actions within the textinput.
|
|
||||||
type KeyMap struct {
|
|
||||||
CharacterForward key.Binding
|
|
||||||
CharacterBackward key.Binding
|
|
||||||
WordForward key.Binding
|
|
||||||
WordBackward key.Binding
|
|
||||||
DeleteWordBackward key.Binding
|
|
||||||
DeleteWordForward key.Binding
|
|
||||||
DeleteAfterCursor key.Binding
|
|
||||||
DeleteBeforeCursor key.Binding
|
|
||||||
DeleteCharacterBackward key.Binding
|
|
||||||
DeleteCharacterForward key.Binding
|
|
||||||
LineStart key.Binding
|
|
||||||
LineEnd key.Binding
|
|
||||||
Paste key.Binding
|
|
||||||
AcceptSuggestion key.Binding
|
|
||||||
NextSuggestion key.Binding
|
|
||||||
PrevSuggestion key.Binding
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultKeyMap is the default set of key bindings for navigating and acting
|
|
||||||
// upon the textinput.
|
|
||||||
var DefaultKeyMap = KeyMap{
|
|
||||||
CharacterForward: key.NewBinding(key.WithKeys("right", "ctrl+f")),
|
|
||||||
CharacterBackward: key.NewBinding(key.WithKeys("left", "ctrl+b")),
|
|
||||||
WordForward: key.NewBinding(key.WithKeys("alt+right", "ctrl+right", "alt+f")),
|
|
||||||
WordBackward: key.NewBinding(key.WithKeys("alt+left", "ctrl+left", "alt+b")),
|
|
||||||
DeleteWordBackward: key.NewBinding(key.WithKeys("alt+backspace", "ctrl+w")),
|
|
||||||
DeleteWordForward: key.NewBinding(key.WithKeys("alt+delete", "alt+d")),
|
|
||||||
DeleteAfterCursor: key.NewBinding(key.WithKeys("ctrl+k")),
|
|
||||||
DeleteBeforeCursor: key.NewBinding(key.WithKeys("ctrl+u")),
|
|
||||||
DeleteCharacterBackward: key.NewBinding(key.WithKeys("backspace", "ctrl+h")),
|
|
||||||
DeleteCharacterForward: key.NewBinding(key.WithKeys("delete", "ctrl+d")),
|
|
||||||
LineStart: key.NewBinding(key.WithKeys("home", "ctrl+a")),
|
|
||||||
LineEnd: key.NewBinding(key.WithKeys("end", "ctrl+e")),
|
|
||||||
Paste: key.NewBinding(key.WithKeys("ctrl+v")),
|
|
||||||
AcceptSuggestion: key.NewBinding(key.WithKeys("tab")),
|
|
||||||
NextSuggestion: key.NewBinding(key.WithKeys("down", "ctrl+n")),
|
|
||||||
PrevSuggestion: key.NewBinding(key.WithKeys("up", "ctrl+p")),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model is the Bubble Tea model for this text input element.
|
|
||||||
type Model struct {
|
|
||||||
Err error
|
|
||||||
|
|
||||||
// General settings.
|
|
||||||
Prompt string
|
|
||||||
Placeholder string
|
|
||||||
EchoMode EchoMode
|
|
||||||
EchoCharacter rune
|
|
||||||
Cursor cursor.Model
|
|
||||||
|
|
||||||
// Deprecated: use [cursor.BlinkSpeed] instead.
|
|
||||||
BlinkSpeed time.Duration
|
|
||||||
|
|
||||||
// Styles. These will be applied as inline styles.
|
|
||||||
//
|
|
||||||
// For an introduction to styling with Lip Gloss see:
|
|
||||||
// https://github.com/charmbracelet/lipgloss
|
|
||||||
PromptStyle lipgloss.Style
|
|
||||||
TextStyle lipgloss.Style
|
|
||||||
PlaceholderStyle lipgloss.Style
|
|
||||||
CompletionStyle lipgloss.Style
|
|
||||||
|
|
||||||
// Deprecated: use Cursor.Style instead.
|
|
||||||
CursorStyle lipgloss.Style
|
|
||||||
|
|
||||||
// CharLimit is the maximum amount of characters this input element will
|
|
||||||
// accept. If 0 or less, there's no limit.
|
|
||||||
CharLimit int
|
|
||||||
|
|
||||||
// Width is the maximum number of characters that can be displayed at once.
|
|
||||||
// It essentially treats the text field like a horizontally scrolling
|
|
||||||
// viewport. If 0 or less this setting is ignored.
|
|
||||||
Width int
|
|
||||||
|
|
||||||
// KeyMap encodes the keybindings recognized by the widget.
|
|
||||||
KeyMap KeyMap
|
|
||||||
|
|
||||||
// Underlying text value.
|
|
||||||
value []rune
|
|
||||||
|
|
||||||
// focus indicates whether user input focus should be on this input
|
|
||||||
// component. When false, ignore keyboard input and hide the cursor.
|
|
||||||
focus bool
|
|
||||||
|
|
||||||
// Cursor position.
|
|
||||||
pos int
|
|
||||||
|
|
||||||
// Used to emulate a viewport when width is set and the content is
|
|
||||||
// overflowing.
|
|
||||||
offset int
|
|
||||||
offsetRight int
|
|
||||||
|
|
||||||
// Validate is a function that checks whether or not the text within the
|
|
||||||
// input is valid. If it is not valid, the `Err` field will be set to the
|
|
||||||
// error returned by the function. If the function is not defined, all
|
|
||||||
// input is considered valid.
|
|
||||||
Validate ValidateFunc
|
|
||||||
|
|
||||||
// rune sanitizer for input.
|
|
||||||
rsan runeutil.Sanitizer
|
|
||||||
|
|
||||||
// Should the input suggest to complete
|
|
||||||
ShowSuggestions bool
|
|
||||||
|
|
||||||
// suggestions is a list of suggestions that may be used to complete the
|
|
||||||
// input.
|
|
||||||
suggestions [][]rune
|
|
||||||
matchedSuggestions [][]rune
|
|
||||||
currentSuggestionIndex int
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new model with default settings.
|
|
||||||
func New() Model {
|
|
||||||
return Model{
|
|
||||||
Prompt: "> ",
|
|
||||||
EchoCharacter: '*',
|
|
||||||
CharLimit: 0,
|
|
||||||
PlaceholderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")),
|
|
||||||
ShowSuggestions: false,
|
|
||||||
CompletionStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")),
|
|
||||||
Cursor: cursor.New(),
|
|
||||||
KeyMap: DefaultKeyMap,
|
|
||||||
|
|
||||||
suggestions: [][]rune{},
|
|
||||||
value: nil,
|
|
||||||
focus: false,
|
|
||||||
pos: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewModel creates a new model with default settings.
|
|
||||||
//
|
|
||||||
// Deprecated: Use [New] instead.
|
|
||||||
var NewModel = New
|
|
||||||
|
|
||||||
// SetValue sets the value of the text input.
|
|
||||||
func (m *Model) SetValue(s string) {
|
|
||||||
// Clean up any special characters in the input provided by the
|
|
||||||
// caller. This avoids bugs due to e.g. tab characters and whatnot.
|
|
||||||
runes := m.san().Sanitize([]rune(s))
|
|
||||||
err := m.validate(runes)
|
|
||||||
m.setValueInternal(runes, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Model) setValueInternal(runes []rune, err error) {
|
|
||||||
m.Err = err
|
|
||||||
|
|
||||||
empty := len(m.value) == 0
|
|
||||||
|
|
||||||
if m.CharLimit > 0 && len(runes) > m.CharLimit {
|
|
||||||
m.value = runes[:m.CharLimit]
|
|
||||||
} else {
|
|
||||||
m.value = runes
|
|
||||||
}
|
|
||||||
if (m.pos == 0 && empty) || m.pos > len(m.value) {
|
|
||||||
m.SetCursor(len(m.value))
|
|
||||||
}
|
|
||||||
m.handleOverflow()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the value of the text input.
|
|
||||||
func (m Model) Value() string {
|
|
||||||
return string(m.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position returns the cursor position.
|
|
||||||
func (m Model) Position() int {
|
|
||||||
return m.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetCursor moves the cursor to the given position. If the position is
|
|
||||||
// out of bounds the cursor will be moved to the start or end accordingly.
|
|
||||||
func (m *Model) SetCursor(pos int) {
|
|
||||||
m.pos = clamp(pos, 0, len(m.value))
|
|
||||||
m.handleOverflow()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CursorStart moves the cursor to the start of the input field.
|
|
||||||
func (m *Model) CursorStart() {
|
|
||||||
m.SetCursor(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CursorEnd moves the cursor to the end of the input field.
|
|
||||||
func (m *Model) CursorEnd() {
|
|
||||||
m.SetCursor(len(m.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focused returns the focus state on the model.
|
|
||||||
func (m Model) Focused() bool {
|
|
||||||
return m.focus
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus sets the focus state on the model. When the model is in focus it can
|
|
||||||
// receive keyboard input and the cursor will be shown.
|
|
||||||
func (m *Model) Focus() tea.Cmd {
|
|
||||||
m.focus = true
|
|
||||||
return m.Cursor.Focus()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blur removes the focus state on the model. When the model is blurred it can
|
|
||||||
// not receive keyboard input and the cursor will be hidden.
|
|
||||||
func (m *Model) Blur() {
|
|
||||||
m.focus = false
|
|
||||||
m.Cursor.Blur()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset sets the input to its default state with no input.
|
|
||||||
func (m *Model) Reset() {
|
|
||||||
m.value = nil
|
|
||||||
m.SetCursor(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSuggestions sets the suggestions for the input.
|
|
||||||
func (m *Model) SetSuggestions(suggestions []string) {
|
|
||||||
m.suggestions = make([][]rune, len(suggestions))
|
|
||||||
for i, s := range suggestions {
|
|
||||||
m.suggestions[i] = []rune(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.updateSuggestions()
|
|
||||||
}
|
|
||||||
|
|
||||||
// rsan initializes or retrieves the rune sanitizer.
|
|
||||||
func (m *Model) san() runeutil.Sanitizer {
|
|
||||||
if m.rsan == nil {
|
|
||||||
// Textinput has all its input on a single line so collapse
|
|
||||||
// newlines/tabs to single spaces.
|
|
||||||
m.rsan = runeutil.NewSanitizer(
|
|
||||||
runeutil.ReplaceTabs(" "), runeutil.ReplaceNewlines(" "))
|
|
||||||
}
|
|
||||||
return m.rsan
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Model) insertRunesFromUserInput(v []rune) {
|
|
||||||
// Clean up any special characters in the input provided by the
|
|
||||||
// clipboard. This avoids bugs due to e.g. tab characters and
|
|
||||||
// whatnot.
|
|
||||||
paste := m.san().Sanitize(v)
|
|
||||||
|
|
||||||
var availSpace int
|
|
||||||
if m.CharLimit > 0 {
|
|
||||||
availSpace = m.CharLimit - len(m.value)
|
|
||||||
|
|
||||||
// If the char limit's been reached, cancel.
|
|
||||||
if availSpace <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's not enough space to paste the whole thing cut the pasted
|
|
||||||
// runes down so they'll fit.
|
|
||||||
if availSpace < len(paste) {
|
|
||||||
paste = paste[:availSpace]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stuff before and after the cursor
|
|
||||||
head := m.value[:m.pos]
|
|
||||||
tailSrc := m.value[m.pos:]
|
|
||||||
tail := make([]rune, len(tailSrc))
|
|
||||||
copy(tail, tailSrc)
|
|
||||||
|
|
||||||
// Insert pasted runes
|
|
||||||
for _, r := range paste {
|
|
||||||
head = append(head, r)
|
|
||||||
m.pos++
|
|
||||||
if m.CharLimit > 0 {
|
|
||||||
availSpace--
|
|
||||||
if availSpace <= 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put it all back together
|
|
||||||
value := append(head, tail...)
|
|
||||||
inputErr := m.validate(value)
|
|
||||||
m.setValueInternal(value, inputErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a max width is defined, perform some logic to treat the visible area
|
|
||||||
// as a horizontally scrolling viewport.
|
|
||||||
func (m *Model) handleOverflow() {
|
|
||||||
if m.Width <= 0 || uniseg.StringWidth(string(m.value)) <= m.Width {
|
|
||||||
m.offset = 0
|
|
||||||
m.offsetRight = len(m.value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Correct right offset if we've deleted characters
|
|
||||||
m.offsetRight = min(m.offsetRight, len(m.value))
|
|
||||||
|
|
||||||
if m.pos < m.offset {
|
|
||||||
m.offset = m.pos
|
|
||||||
|
|
||||||
w := 0
|
|
||||||
i := 0
|
|
||||||
runes := m.value[m.offset:]
|
|
||||||
|
|
||||||
for i < len(runes) && w <= m.Width {
|
|
||||||
w += rw.RuneWidth(runes[i])
|
|
||||||
if w <= m.Width+1 {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.offsetRight = m.offset + i
|
|
||||||
} else if m.pos >= m.offsetRight {
|
|
||||||
m.offsetRight = m.pos
|
|
||||||
|
|
||||||
w := 0
|
|
||||||
runes := m.value[:m.offsetRight]
|
|
||||||
i := len(runes) - 1
|
|
||||||
|
|
||||||
for i > 0 && w < m.Width {
|
|
||||||
w += rw.RuneWidth(runes[i])
|
|
||||||
if w <= m.Width {
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.offset = m.offsetRight - (len(runes) - 1 - i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteBeforeCursor deletes all text before the cursor.
|
|
||||||
func (m *Model) deleteBeforeCursor() {
|
|
||||||
m.value = m.value[m.pos:]
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
m.offset = 0
|
|
||||||
m.SetCursor(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteAfterCursor deletes all text after the cursor. If input is masked
|
|
||||||
// delete everything after the cursor so as not to reveal word breaks in the
|
|
||||||
// masked input.
|
|
||||||
func (m *Model) deleteAfterCursor() {
|
|
||||||
m.value = m.value[:m.pos]
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
m.SetCursor(len(m.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteWordBackward deletes the word left to the cursor.
|
|
||||||
func (m *Model) deleteWordBackward() {
|
|
||||||
if m.pos == 0 || len(m.value) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.EchoMode != EchoNormal {
|
|
||||||
m.deleteBeforeCursor()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linter note: it's critical that we acquire the initial cursor position
|
|
||||||
// here prior to altering it via SetCursor() below. As such, moving this
|
|
||||||
// call into the corresponding if clause does not apply here.
|
|
||||||
oldPos := m.pos //nolint:ifshort
|
|
||||||
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
for unicode.IsSpace(m.value[m.pos]) {
|
|
||||||
if m.pos <= 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// ignore series of whitespace before cursor
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
for m.pos > 0 {
|
|
||||||
if !unicode.IsSpace(m.value[m.pos]) {
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
} else {
|
|
||||||
if m.pos > 0 {
|
|
||||||
// keep the previous space
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if oldPos > len(m.value) {
|
|
||||||
m.value = m.value[:m.pos]
|
|
||||||
} else {
|
|
||||||
m.value = append(m.value[:m.pos], m.value[oldPos:]...)
|
|
||||||
}
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteWordForward deletes the word right to the cursor. If input is masked
|
|
||||||
// delete everything after the cursor so as not to reveal word breaks in the
|
|
||||||
// masked input.
|
|
||||||
func (m *Model) deleteWordForward() {
|
|
||||||
if m.pos >= len(m.value) || len(m.value) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.EchoMode != EchoNormal {
|
|
||||||
m.deleteAfterCursor()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
oldPos := m.pos
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
for unicode.IsSpace(m.value[m.pos]) {
|
|
||||||
// ignore series of whitespace after cursor
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
|
|
||||||
if m.pos >= len(m.value) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for m.pos < len(m.value) {
|
|
||||||
if !unicode.IsSpace(m.value[m.pos]) {
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.pos > len(m.value) {
|
|
||||||
m.value = m.value[:oldPos]
|
|
||||||
} else {
|
|
||||||
m.value = append(m.value[:oldPos], m.value[m.pos:]...)
|
|
||||||
}
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
|
|
||||||
m.SetCursor(oldPos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wordBackward moves the cursor one word to the left. If input is masked, move
|
|
||||||
// input to the start so as not to reveal word breaks in the masked input.
|
|
||||||
func (m *Model) wordBackward() {
|
|
||||||
if m.pos == 0 || len(m.value) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.EchoMode != EchoNormal {
|
|
||||||
m.CursorStart()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
i := m.pos - 1
|
|
||||||
for i >= 0 {
|
|
||||||
if unicode.IsSpace(m.value[i]) {
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
i--
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i >= 0 {
|
|
||||||
if !unicode.IsSpace(m.value[i]) {
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
i--
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wordForward moves the cursor one word to the right. If the input is masked,
|
|
||||||
// move input to the end so as not to reveal word breaks in the masked input.
|
|
||||||
func (m *Model) wordForward() {
|
|
||||||
if m.pos >= len(m.value) || len(m.value) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.EchoMode != EchoNormal {
|
|
||||||
m.CursorEnd()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
i := m.pos
|
|
||||||
for i < len(m.value) {
|
|
||||||
if unicode.IsSpace(m.value[i]) {
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
i++
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i < len(m.value) {
|
|
||||||
if !unicode.IsSpace(m.value[i]) {
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
i++
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Model) echoTransform(v string) string {
|
|
||||||
switch m.EchoMode {
|
|
||||||
case EchoPassword:
|
|
||||||
return strings.Repeat(string(m.EchoCharacter), uniseg.StringWidth(v))
|
|
||||||
case EchoNone:
|
|
||||||
return ""
|
|
||||||
case EchoNormal:
|
|
||||||
return v
|
|
||||||
default:
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is the Bubble Tea update loop.
|
|
||||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|
||||||
if !m.focus {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to check for completion before, because key is configurable and might be double assigned
|
|
||||||
keyMsg, ok := msg.(tea.KeyMsg)
|
|
||||||
if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) {
|
|
||||||
if m.canAcceptSuggestion() {
|
|
||||||
m.value = append(m.value, m.matchedSuggestions[m.currentSuggestionIndex][len(m.value):]...)
|
|
||||||
m.CursorEnd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's remember where the position of the cursor currently is so that if
|
|
||||||
// the cursor position changes, we can reset the blink.
|
|
||||||
oldPos := m.pos
|
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
|
||||||
case tea.KeyMsg:
|
|
||||||
switch {
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteWordBackward):
|
|
||||||
m.deleteWordBackward()
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteCharacterBackward):
|
|
||||||
m.Err = nil
|
|
||||||
if len(m.value) > 0 {
|
|
||||||
m.value = append(m.value[:max(0, m.pos-1)], m.value[m.pos:]...)
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
if m.pos > 0 {
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case key.Matches(msg, m.KeyMap.WordBackward):
|
|
||||||
m.wordBackward()
|
|
||||||
case key.Matches(msg, m.KeyMap.CharacterBackward):
|
|
||||||
if m.pos > 0 {
|
|
||||||
m.SetCursor(m.pos - 1)
|
|
||||||
}
|
|
||||||
case key.Matches(msg, m.KeyMap.WordForward):
|
|
||||||
m.wordForward()
|
|
||||||
case key.Matches(msg, m.KeyMap.CharacterForward):
|
|
||||||
if m.pos < len(m.value) {
|
|
||||||
m.SetCursor(m.pos + 1)
|
|
||||||
}
|
|
||||||
case key.Matches(msg, m.KeyMap.LineStart):
|
|
||||||
m.CursorStart()
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteCharacterForward):
|
|
||||||
if len(m.value) > 0 && m.pos < len(m.value) {
|
|
||||||
m.value = append(m.value[:m.pos], m.value[m.pos+1:]...)
|
|
||||||
m.Err = m.validate(m.value)
|
|
||||||
}
|
|
||||||
case key.Matches(msg, m.KeyMap.LineEnd):
|
|
||||||
m.CursorEnd()
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteAfterCursor):
|
|
||||||
m.deleteAfterCursor()
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteBeforeCursor):
|
|
||||||
m.deleteBeforeCursor()
|
|
||||||
case key.Matches(msg, m.KeyMap.Paste):
|
|
||||||
return m, Paste
|
|
||||||
case key.Matches(msg, m.KeyMap.DeleteWordForward):
|
|
||||||
m.deleteWordForward()
|
|
||||||
case key.Matches(msg, m.KeyMap.NextSuggestion):
|
|
||||||
m.nextSuggestion()
|
|
||||||
case key.Matches(msg, m.KeyMap.PrevSuggestion):
|
|
||||||
m.previousSuggestion()
|
|
||||||
default:
|
|
||||||
// Input one or more regular characters.
|
|
||||||
m.insertRunesFromUserInput(msg.Runes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check again if can be completed
|
|
||||||
// because value might be something that does not match the completion prefix
|
|
||||||
m.updateSuggestions()
|
|
||||||
|
|
||||||
case pasteMsg:
|
|
||||||
m.insertRunesFromUserInput([]rune(msg))
|
|
||||||
|
|
||||||
case pasteErrMsg:
|
|
||||||
m.Err = msg
|
|
||||||
}
|
|
||||||
|
|
||||||
var cmds []tea.Cmd
|
|
||||||
var cmd tea.Cmd
|
|
||||||
|
|
||||||
m.Cursor, cmd = m.Cursor.Update(msg)
|
|
||||||
cmds = append(cmds, cmd)
|
|
||||||
|
|
||||||
if oldPos != m.pos && m.Cursor.Mode() == cursor.CursorBlink {
|
|
||||||
m.Cursor.Blink = false
|
|
||||||
cmds = append(cmds, m.Cursor.BlinkCmd())
|
|
||||||
}
|
|
||||||
|
|
||||||
m.handleOverflow()
|
|
||||||
return m, tea.Batch(cmds...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// View renders the textinput in its current state.
|
|
||||||
func (m Model) View() string {
|
|
||||||
// Placeholder text
|
|
||||||
if len(m.value) == 0 && m.Placeholder != "" {
|
|
||||||
return m.placeholderView()
|
|
||||||
}
|
|
||||||
|
|
||||||
styleText := m.TextStyle.Inline(true).Render
|
|
||||||
|
|
||||||
value := m.value[m.offset:m.offsetRight]
|
|
||||||
pos := max(0, m.pos-m.offset)
|
|
||||||
v := styleText(m.echoTransform(string(value[:pos])))
|
|
||||||
|
|
||||||
if pos < len(value) { //nolint:nestif
|
|
||||||
char := m.echoTransform(string(value[pos]))
|
|
||||||
m.Cursor.SetChar(char)
|
|
||||||
v += m.Cursor.View() // cursor and text under it
|
|
||||||
v += styleText(m.echoTransform(string(value[pos+1:]))) // text after cursor
|
|
||||||
v += m.completionView(0) // suggested completion
|
|
||||||
} else {
|
|
||||||
if m.focus && m.canAcceptSuggestion() {
|
|
||||||
suggestion := m.matchedSuggestions[m.currentSuggestionIndex]
|
|
||||||
if len(value) < len(suggestion) {
|
|
||||||
m.Cursor.TextStyle = m.CompletionStyle
|
|
||||||
m.Cursor.SetChar(m.echoTransform(string(suggestion[pos])))
|
|
||||||
v += m.Cursor.View()
|
|
||||||
v += m.completionView(1)
|
|
||||||
} else {
|
|
||||||
m.Cursor.SetChar(" ")
|
|
||||||
v += m.Cursor.View()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m.Cursor.SetChar(" ")
|
|
||||||
v += m.Cursor.View()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a max width and background color were set fill the empty spaces with
|
|
||||||
// the background color.
|
|
||||||
valWidth := uniseg.StringWidth(string(value))
|
|
||||||
if m.Width > 0 && valWidth <= m.Width {
|
|
||||||
padding := max(0, m.Width-valWidth)
|
|
||||||
if valWidth+padding <= m.Width && pos < len(value) {
|
|
||||||
padding++
|
|
||||||
}
|
|
||||||
v += styleText(strings.Repeat(" ", padding))
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.PromptStyle.Render(m.Prompt) + v
|
|
||||||
}
|
|
||||||
|
|
||||||
// placeholderView returns the prompt and placeholder view, if any.
|
|
||||||
func (m Model) placeholderView() string {
|
|
||||||
var (
|
|
||||||
v string
|
|
||||||
style = m.PlaceholderStyle.Inline(true).Render
|
|
||||||
)
|
|
||||||
|
|
||||||
p := make([]rune, m.Width+1)
|
|
||||||
copy(p, []rune(m.Placeholder))
|
|
||||||
|
|
||||||
m.Cursor.TextStyle = m.PlaceholderStyle
|
|
||||||
m.Cursor.SetChar(string(p[:1]))
|
|
||||||
v += m.Cursor.View()
|
|
||||||
|
|
||||||
// If the entire placeholder is already set and no padding is needed, finish
|
|
||||||
if m.Width < 1 && len(p) <= 1 {
|
|
||||||
return m.PromptStyle.Render(m.Prompt) + v
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Width is set then size placeholder accordingly
|
|
||||||
if m.Width > 0 {
|
|
||||||
// available width is width - len + cursor offset of 1
|
|
||||||
minWidth := lipgloss.Width(m.Placeholder)
|
|
||||||
availWidth := m.Width - minWidth + 1
|
|
||||||
|
|
||||||
// if width < len, 'subtract'(add) number to len and dont add padding
|
|
||||||
if availWidth < 0 {
|
|
||||||
minWidth += availWidth
|
|
||||||
availWidth = 0
|
|
||||||
}
|
|
||||||
// append placeholder[len] - cursor, append padding
|
|
||||||
v += style(string(p[1:minWidth]))
|
|
||||||
v += style(strings.Repeat(" ", availWidth))
|
|
||||||
} else {
|
|
||||||
// if there is no width, the placeholder can be any length
|
|
||||||
v += style(string(p[1:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.PromptStyle.Render(m.Prompt) + v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blink is a command used to initialize cursor blinking.
|
|
||||||
func Blink() tea.Msg {
|
|
||||||
return cursor.Blink()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paste is a command for pasting from the clipboard into the text input.
|
|
||||||
func Paste() tea.Msg {
|
|
||||||
str, err := clipboard.ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
return pasteErrMsg{err}
|
|
||||||
}
|
|
||||||
return pasteMsg(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func clamp(v, low, high int) int {
|
|
||||||
if high < low {
|
|
||||||
low, high = high, low
|
|
||||||
}
|
|
||||||
return min(high, max(low, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated.
|
|
||||||
|
|
||||||
// Deprecated: use [cursor.Mode].
|
|
||||||
//
|
|
||||||
//nolint:revive
|
|
||||||
type CursorMode int
|
|
||||||
|
|
||||||
//nolint:revive
|
|
||||||
const (
|
|
||||||
// Deprecated: use [cursor.CursorBlink].
|
|
||||||
CursorBlink = CursorMode(cursor.CursorBlink)
|
|
||||||
// Deprecated: use [cursor.CursorStatic].
|
|
||||||
CursorStatic = CursorMode(cursor.CursorStatic)
|
|
||||||
// Deprecated: use [cursor.CursorHide].
|
|
||||||
CursorHide = CursorMode(cursor.CursorHide)
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c CursorMode) String() string {
|
|
||||||
return cursor.Mode(c).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: use [cursor.Mode].
|
|
||||||
//
|
|
||||||
//nolint:revive
|
|
||||||
func (m Model) CursorMode() CursorMode {
|
|
||||||
return CursorMode(m.Cursor.Mode())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: use cursor.SetMode().
|
|
||||||
//
|
|
||||||
//nolint:revive
|
|
||||||
func (m *Model) SetCursorMode(mode CursorMode) tea.Cmd {
|
|
||||||
return m.Cursor.SetMode(cursor.Mode(mode))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Model) completionView(offset int) string {
|
|
||||||
var (
|
|
||||||
value = m.value
|
|
||||||
style = m.PlaceholderStyle.Inline(true).Render
|
|
||||||
)
|
|
||||||
|
|
||||||
if m.canAcceptSuggestion() {
|
|
||||||
suggestion := m.matchedSuggestions[m.currentSuggestionIndex]
|
|
||||||
if len(value) < len(suggestion) {
|
|
||||||
return style(string(suggestion[len(value)+offset:]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Model) getSuggestions(sugs [][]rune) []string {
|
|
||||||
suggestions := make([]string, len(sugs))
|
|
||||||
for i, s := range sugs {
|
|
||||||
suggestions[i] = string(s)
|
|
||||||
}
|
|
||||||
return suggestions
|
|
||||||
}
|
|
||||||
|
|
||||||
// AvailableSuggestions returns the list of available suggestions.
|
|
||||||
func (m *Model) AvailableSuggestions() []string {
|
|
||||||
return m.getSuggestions(m.suggestions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchedSuggestions returns the list of matched suggestions.
|
|
||||||
func (m *Model) MatchedSuggestions() []string {
|
|
||||||
return m.getSuggestions(m.matchedSuggestions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentSuggestionIndex returns the currently selected suggestion index.
|
|
||||||
func (m *Model) CurrentSuggestionIndex() int {
|
|
||||||
return m.currentSuggestionIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentSuggestion returns the currently selected suggestion.
|
|
||||||
func (m *Model) CurrentSuggestion() string {
|
|
||||||
if m.currentSuggestionIndex >= len(m.matchedSuggestions) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(m.matchedSuggestions[m.currentSuggestionIndex])
|
|
||||||
}
|
|
||||||
|
|
||||||
// canAcceptSuggestion returns whether there is an acceptable suggestion to
|
|
||||||
// autocomplete the current value.
|
|
||||||
func (m *Model) canAcceptSuggestion() bool {
|
|
||||||
return len(m.matchedSuggestions) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateSuggestions refreshes the list of matching suggestions.
|
|
||||||
func (m *Model) updateSuggestions() {
|
|
||||||
if !m.ShowSuggestions {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(m.value) <= 0 || len(m.suggestions) <= 0 {
|
|
||||||
m.matchedSuggestions = [][]rune{}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := [][]rune{}
|
|
||||||
for _, s := range m.suggestions {
|
|
||||||
suggestion := string(s)
|
|
||||||
|
|
||||||
if strings.HasPrefix(strings.ToLower(suggestion), strings.ToLower(string(m.value))) {
|
|
||||||
matches = append(matches, []rune(suggestion))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(matches, m.matchedSuggestions) {
|
|
||||||
m.currentSuggestionIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
m.matchedSuggestions = matches
|
|
||||||
}
|
|
||||||
|
|
||||||
// nextSuggestion selects the next suggestion.
|
|
||||||
func (m *Model) nextSuggestion() {
|
|
||||||
m.currentSuggestionIndex = (m.currentSuggestionIndex + 1)
|
|
||||||
if m.currentSuggestionIndex >= len(m.matchedSuggestions) {
|
|
||||||
m.currentSuggestionIndex = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// previousSuggestion selects the previous suggestion.
|
|
||||||
func (m *Model) previousSuggestion() {
|
|
||||||
m.currentSuggestionIndex = (m.currentSuggestionIndex - 1)
|
|
||||||
if m.currentSuggestionIndex < 0 {
|
|
||||||
m.currentSuggestionIndex = len(m.matchedSuggestions) - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Model) validate(v []rune) error {
|
|
||||||
if m.Validate != nil {
|
|
||||||
return m.Validate(string(v))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
33
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
33
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
@ -153,29 +153,24 @@ func envColorProfile(env environ) (p Profile) {
|
|||||||
p = ANSI
|
p = ANSI
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(term, "-")
|
switch {
|
||||||
switch parts[0] {
|
case strings.Contains(term, "alacritty"),
|
||||||
case "alacritty",
|
strings.Contains(term, "contour"),
|
||||||
"contour",
|
strings.Contains(term, "foot"),
|
||||||
"foot",
|
strings.Contains(term, "ghostty"),
|
||||||
"ghostty",
|
strings.Contains(term, "kitty"),
|
||||||
"kitty",
|
strings.Contains(term, "rio"),
|
||||||
"rio",
|
strings.Contains(term, "st"),
|
||||||
"st",
|
strings.Contains(term, "wezterm"):
|
||||||
"wezterm":
|
|
||||||
return TrueColor
|
return TrueColor
|
||||||
case "xterm":
|
case strings.HasPrefix(term, "tmux"), strings.HasPrefix(term, "screen"):
|
||||||
if len(parts) > 1 {
|
|
||||||
switch parts[1] {
|
|
||||||
case "ghostty", "kitty":
|
|
||||||
// These terminals can be defined as xterm-TERMNAME
|
|
||||||
return TrueColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "tmux", "screen":
|
|
||||||
if p < ANSI256 {
|
if p < ANSI256 {
|
||||||
p = ANSI256
|
p = ANSI256
|
||||||
}
|
}
|
||||||
|
case strings.HasPrefix(term, "xterm"):
|
||||||
|
if p < ANSI {
|
||||||
|
p = ANSI
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isCloudShell, _ := strconv.ParseBool(env.get("GOOGLE_CLOUD_SHELL")); isCloudShell {
|
if isCloudShell, _ := strconv.ParseBool(env.get("GOOGLE_CLOUD_SHELL")); isCloudShell {
|
||||||
|
|||||||
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) {
|
func setMode(reset bool, modes ...Mode) (s string) {
|
||||||
if len(modes) == 0 {
|
if len(modes) == 0 {
|
||||||
return //nolint:nakedret
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := "h"
|
cmd := "h"
|
||||||
@ -142,7 +142,7 @@ func setMode(reset bool, modes ...Mode) (s string) {
|
|||||||
if len(dec) > 0 {
|
if len(dec) > 0 {
|
||||||
s += seq + "?" + strings.Join(dec, ";") + cmd
|
s += seq + "?" + strings.Join(dec, ";") + cmd
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestMode (DECRQM) returns a sequence to request a mode from the terminal.
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/KAM.html
|
||||||
const (
|
const (
|
||||||
KeyboardActionMode = ANSIMode(2)
|
ModeKeyboardAction = ANSIMode(2)
|
||||||
KAM = KeyboardActionMode
|
KAM = ModeKeyboardAction
|
||||||
|
|
||||||
SetKeyboardActionMode = "\x1b[2h"
|
SetModeKeyboardAction = "\x1b[2h"
|
||||||
ResetKeyboardActionMode = "\x1b[2l"
|
ResetModeKeyboardAction = "\x1b[2l"
|
||||||
RequestKeyboardActionMode = "\x1b[2$p"
|
RequestModeKeyboardAction = "\x1b[2$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Insert/Replace Mode (IRM) is a mode that determines whether characters are
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/IRM.html
|
||||||
const (
|
const (
|
||||||
InsertReplaceMode = ANSIMode(4)
|
ModeInsertReplace = ANSIMode(4)
|
||||||
IRM = InsertReplaceMode
|
IRM = ModeInsertReplace
|
||||||
|
|
||||||
SetInsertReplaceMode = "\x1b[4h"
|
SetModeInsertReplace = "\x1b[4h"
|
||||||
ResetInsertReplaceMode = "\x1b[4l"
|
ResetModeInsertReplace = "\x1b[4l"
|
||||||
RequestInsertReplaceMode = "\x1b[4$p"
|
RequestModeInsertReplace = "\x1b[4$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BiDirectional Support Mode (BDSM) is a mode that determines whether the
|
// BiDirectional Support Mode (BDSM) is a mode that determines whether the
|
||||||
@ -260,12 +260,12 @@ const (
|
|||||||
//
|
//
|
||||||
// See ECMA-48 7.2.1.
|
// See ECMA-48 7.2.1.
|
||||||
const (
|
const (
|
||||||
BiDirectionalSupportMode = ANSIMode(8)
|
ModeBiDirectionalSupport = ANSIMode(8)
|
||||||
BDSM = BiDirectionalSupportMode
|
BDSM = ModeBiDirectionalSupport
|
||||||
|
|
||||||
SetBiDirectionalSupportMode = "\x1b[8h"
|
SetModeBiDirectionalSupport = "\x1b[8h"
|
||||||
ResetBiDirectionalSupportMode = "\x1b[8l"
|
ResetModeBiDirectionalSupport = "\x1b[8l"
|
||||||
RequestBiDirectionalSupportMode = "\x1b[8$p"
|
RequestModeBiDirectionalSupport = "\x1b[8$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Send Receive Mode (SRM) or Local Echo Mode is a mode that determines whether
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/SRM.html
|
||||||
const (
|
const (
|
||||||
SendReceiveMode = ANSIMode(12)
|
ModeSendReceive = ANSIMode(12)
|
||||||
LocalEchoMode = SendReceiveMode
|
ModeLocalEcho = ModeSendReceive
|
||||||
SRM = SendReceiveMode
|
SRM = ModeSendReceive
|
||||||
|
|
||||||
SetSendReceiveMode = "\x1b[12h"
|
SetModeSendReceive = "\x1b[12h"
|
||||||
ResetSendReceiveMode = "\x1b[12l"
|
ResetModeSendReceive = "\x1b[12l"
|
||||||
RequestSendReceiveMode = "\x1b[12$p"
|
RequestModeSendReceive = "\x1b[12$p"
|
||||||
|
|
||||||
SetLocalEchoMode = "\x1b[12h"
|
SetModeLocalEcho = "\x1b[12h"
|
||||||
ResetLocalEchoMode = "\x1b[12l"
|
ResetModeLocalEcho = "\x1b[12l"
|
||||||
RequestLocalEchoMode = "\x1b[12$p"
|
RequestModeLocalEcho = "\x1b[12$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Line Feed/New Line Mode (LNM) is a mode that determines whether the terminal
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/LNM.html
|
||||||
const (
|
const (
|
||||||
LineFeedNewLineMode = ANSIMode(20)
|
ModeLineFeedNewLine = ANSIMode(20)
|
||||||
LNM = LineFeedNewLineMode
|
LNM = ModeLineFeedNewLine
|
||||||
|
|
||||||
SetLineFeedNewLineMode = "\x1b[20h"
|
SetModeLineFeedNewLine = "\x1b[20h"
|
||||||
ResetLineFeedNewLineMode = "\x1b[20l"
|
ResetModeLineFeedNewLine = "\x1b[20l"
|
||||||
RequestLineFeedNewLineMode = "\x1b[20$p"
|
RequestModeLineFeedNewLine = "\x1b[20$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cursor Keys Mode (DECCKM) is a mode that determines whether the cursor keys
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECCKM.html
|
||||||
const (
|
const (
|
||||||
CursorKeysMode = DECMode(1)
|
ModeCursorKeys = DECMode(1)
|
||||||
DECCKM = CursorKeysMode
|
DECCKM = ModeCursorKeys
|
||||||
|
|
||||||
SetCursorKeysMode = "\x1b[?1h"
|
SetModeCursorKeys = "\x1b[?1h"
|
||||||
ResetCursorKeysMode = "\x1b[?1l"
|
ResetModeCursorKeys = "\x1b[?1l"
|
||||||
RequestCursorKeysMode = "\x1b[?1$p"
|
RequestModeCursorKeys = "\x1b[?1$p"
|
||||||
)
|
|
||||||
|
|
||||||
// Deprecated: use [SetCursorKeysMode] and [ResetCursorKeysMode] instead.
|
|
||||||
const (
|
|
||||||
EnableCursorKeys = "\x1b[?1h" //nolint:revive // grouped constants
|
|
||||||
DisableCursorKeys = "\x1b[?1l"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Origin Mode (DECOM) is a mode that determines whether the cursor moves to the
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECOM.html
|
||||||
const (
|
const (
|
||||||
OriginMode = DECMode(6)
|
ModeOrigin = DECMode(6)
|
||||||
DECOM = OriginMode
|
DECOM = ModeOrigin
|
||||||
|
|
||||||
SetOriginMode = "\x1b[?6h"
|
SetModeOrigin = "\x1b[?6h"
|
||||||
ResetOriginMode = "\x1b[?6l"
|
ResetModeOrigin = "\x1b[?6l"
|
||||||
RequestOriginMode = "\x1b[?6$p"
|
RequestModeOrigin = "\x1b[?6$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Auto Wrap Mode (DECAWM) is a mode that determines whether the cursor wraps
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECAWM.html
|
||||||
const (
|
const (
|
||||||
AutoWrapMode = DECMode(7)
|
ModeAutoWrap = DECMode(7)
|
||||||
DECAWM = AutoWrapMode
|
DECAWM = ModeAutoWrap
|
||||||
|
|
||||||
SetAutoWrapMode = "\x1b[?7h"
|
SetModeAutoWrap = "\x1b[?7h"
|
||||||
ResetAutoWrapMode = "\x1b[?7l"
|
ResetModeAutoWrap = "\x1b[?7l"
|
||||||
RequestAutoWrapMode = "\x1b[?7$p"
|
RequestModeAutoWrap = "\x1b[?7$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// X10 Mouse Mode is a mode that determines whether the mouse reports on button
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
X10MouseMode = DECMode(9)
|
ModeMouseX10 = DECMode(9)
|
||||||
|
|
||||||
SetX10MouseMode = "\x1b[?9h"
|
SetModeMouseX10 = "\x1b[?9h"
|
||||||
ResetX10MouseMode = "\x1b[?9l"
|
ResetModeMouseX10 = "\x1b[?9l"
|
||||||
RequestX10MouseMode = "\x1b[?9$p"
|
RequestModeMouseX10 = "\x1b[?9$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor.
|
// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor.
|
||||||
//
|
//
|
||||||
// See: https://vt100.net/docs/vt510-rm/DECTCEM.html
|
// See: https://vt100.net/docs/vt510-rm/DECTCEM.html
|
||||||
const (
|
const (
|
||||||
TextCursorEnableMode = DECMode(25)
|
ModeTextCursorEnable = DECMode(25)
|
||||||
DECTCEM = TextCursorEnableMode
|
DECTCEM = ModeTextCursorEnable
|
||||||
|
|
||||||
SetTextCursorEnableMode = "\x1b[?25h"
|
SetModeTextCursorEnable = "\x1b[?25h"
|
||||||
ResetTextCursorEnableMode = "\x1b[?25l"
|
ResetModeTextCursorEnable = "\x1b[?25l"
|
||||||
RequestTextCursorEnableMode = "\x1b[?25$p"
|
RequestModeTextCursorEnable = "\x1b[?25$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// These are aliases for [SetTextCursorEnableMode] and [ResetTextCursorEnableMode].
|
// These are aliases for [SetModeTextCursorEnable] and [ResetModeTextCursorEnable].
|
||||||
const (
|
const (
|
||||||
ShowCursor = SetTextCursorEnableMode
|
ShowCursor = SetModeTextCursorEnable
|
||||||
HideCursor = ResetTextCursorEnableMode
|
HideCursor = ResetModeTextCursorEnable
|
||||||
)
|
|
||||||
|
|
||||||
// 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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Numeric Keypad Mode (DECNKM) is a mode that determines whether the keypad
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECNKM.html
|
||||||
const (
|
const (
|
||||||
NumericKeypadMode = DECMode(66)
|
ModeNumericKeypad = DECMode(66)
|
||||||
DECNKM = NumericKeypadMode
|
DECNKM = ModeNumericKeypad
|
||||||
|
|
||||||
SetNumericKeypadMode = "\x1b[?66h"
|
SetModeNumericKeypad = "\x1b[?66h"
|
||||||
ResetNumericKeypadMode = "\x1b[?66l"
|
ResetModeNumericKeypad = "\x1b[?66l"
|
||||||
RequestNumericKeypadMode = "\x1b[?66$p"
|
RequestModeNumericKeypad = "\x1b[?66$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backarrow Key Mode (DECBKM) is a mode that determines whether the backspace
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECBKM.html
|
||||||
const (
|
const (
|
||||||
BackarrowKeyMode = DECMode(67)
|
ModeBackarrowKey = DECMode(67)
|
||||||
DECBKM = BackarrowKeyMode
|
DECBKM = ModeBackarrowKey
|
||||||
|
|
||||||
SetBackarrowKeyMode = "\x1b[?67h"
|
SetModeBackarrowKey = "\x1b[?67h"
|
||||||
ResetBackarrowKeyMode = "\x1b[?67l"
|
ResetModeBackarrowKey = "\x1b[?67l"
|
||||||
RequestBackarrowKeyMode = "\x1b[?67$p"
|
RequestModeBackarrowKey = "\x1b[?67$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Left Right Margin Mode (DECLRMM) is a mode that determines whether the left
|
// 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
|
// See: https://vt100.net/docs/vt510-rm/DECLRMM.html
|
||||||
const (
|
const (
|
||||||
LeftRightMarginMode = DECMode(69)
|
ModeLeftRightMargin = DECMode(69)
|
||||||
DECLRMM = LeftRightMarginMode
|
DECLRMM = ModeLeftRightMargin
|
||||||
|
|
||||||
SetLeftRightMarginMode = "\x1b[?69h"
|
SetModeLeftRightMargin = "\x1b[?69h"
|
||||||
ResetLeftRightMarginMode = "\x1b[?69l"
|
ResetModeLeftRightMargin = "\x1b[?69l"
|
||||||
RequestLeftRightMarginMode = "\x1b[?69$p"
|
RequestModeLeftRightMargin = "\x1b[?69$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Normal Mouse Mode is a mode that determines whether the mouse reports on
|
// Normal Mouse Mode is a mode that determines whether the mouse reports on
|
||||||
// button presses and releases. It will also report modifier keys, wheel
|
// button presses and releases. It will also report modifier keys, wheel
|
||||||
// events, and extra buttons.
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
NormalMouseMode = DECMode(1000)
|
ModeMouseNormal = DECMode(1000)
|
||||||
|
|
||||||
SetNormalMouseMode = "\x1b[?1000h"
|
SetModeMouseNormal = "\x1b[?1000h"
|
||||||
ResetNormalMouseMode = "\x1b[?1000l"
|
ResetModeMouseNormal = "\x1b[?1000l"
|
||||||
RequestNormalMouseMode = "\x1b[?1000$p"
|
RequestModeMouseNormal = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Highlight Mouse Tracking is a mode that determines whether the mouse reports
|
// Highlight Mouse Tracking is a mode that determines whether the mouse reports
|
||||||
// on button presses, releases, and highlighted cells.
|
// 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:
|
// 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.
|
// Where the parameters are startx, starty, endx, endy, mousex, and mousey.
|
||||||
const (
|
const (
|
||||||
HighlightMouseMode = DECMode(1001)
|
ModeMouseHighlight = DECMode(1001)
|
||||||
|
|
||||||
SetHighlightMouseMode = "\x1b[?1001h"
|
SetModeMouseHighlight = "\x1b[?1001h"
|
||||||
ResetHighlightMouseMode = "\x1b[?1001l"
|
ResetModeMouseHighlight = "\x1b[?1001l"
|
||||||
RequestHighlightMouseMode = "\x1b[?1001$p"
|
RequestModeMouseHighlight = "\x1b[?1001$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VT Hilite Mouse Tracking is a mode that determines whether the mouse reports on
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
//
|
//
|
||||||
// Deprecated: use [HighlightMouseMode] instead.
|
|
||||||
const (
|
|
||||||
MouseHiliteMode = DECMode(1001)
|
|
||||||
|
|
||||||
EnableMouseHilite = "\x1b[?1001h"
|
// Button Event Mouse Tracking is essentially the same as [ModeMouseNormal],
|
||||||
DisableMouseHilite = "\x1b[?1001l"
|
|
||||||
RequestMouseHilite = "\x1b[?1001$p"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Button Event Mouse Tracking is essentially the same as [NormalMouseMode],
|
|
||||||
// but it also reports button-motion events when a button is pressed.
|
// but it also reports button-motion events when a button is pressed.
|
||||||
//
|
//
|
||||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
ButtonEventMouseMode = DECMode(1002)
|
ModeMouseButtonEvent = DECMode(1002)
|
||||||
|
|
||||||
SetButtonEventMouseMode = "\x1b[?1002h"
|
SetModeMouseButtonEvent = "\x1b[?1002h"
|
||||||
ResetButtonEventMouseMode = "\x1b[?1002l"
|
ResetModeMouseButtonEvent = "\x1b[?1002l"
|
||||||
RequestButtonEventMouseMode = "\x1b[?1002$p"
|
RequestModeMouseButtonEvent = "\x1b[?1002$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cell Motion Mouse Tracking is a mode that determines whether the mouse
|
// Any Event Mouse Tracking is the same as [ModeMouseButtonEvent], except that
|
||||||
// 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
|
|
||||||
// all motion events are reported even if no mouse buttons are pressed.
|
// all motion events are reported even if no mouse buttons are pressed.
|
||||||
//
|
//
|
||||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
AnyEventMouseMode = DECMode(1003)
|
ModeMouseAnyEvent = DECMode(1003)
|
||||||
|
|
||||||
SetAnyEventMouseMode = "\x1b[?1003h"
|
SetModeMouseAnyEvent = "\x1b[?1003h"
|
||||||
ResetAnyEventMouseMode = "\x1b[?1003l"
|
ResetModeMouseAnyEvent = "\x1b[?1003l"
|
||||||
RequestAnyEventMouseMode = "\x1b[?1003$p"
|
RequestModeMouseAnyEvent = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Focus Event Mode is a mode that determines whether the terminal reports focus
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Focus-Tracking
|
||||||
const (
|
const (
|
||||||
FocusEventMode = DECMode(1004)
|
ModeFocusEvent = DECMode(1004)
|
||||||
|
|
||||||
SetFocusEventMode = "\x1b[?1004h"
|
SetModeFocusEvent = "\x1b[?1004h"
|
||||||
ResetFocusEventMode = "\x1b[?1004l"
|
ResetModeFocusEvent = "\x1b[?1004l"
|
||||||
RequestFocusEventMode = "\x1b[?1004$p"
|
RequestModeFocusEvent = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SGR Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
// SGR Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
||||||
@ -589,24 +512,15 @@ const (
|
|||||||
//
|
//
|
||||||
// CSI < Cb ; Cx ; Cy M
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
SgrExtMouseMode = DECMode(1006)
|
ModeMouseExtSgr = DECMode(1006)
|
||||||
|
|
||||||
SetSgrExtMouseMode = "\x1b[?1006h"
|
SetModeMouseExtSgr = "\x1b[?1006h"
|
||||||
ResetSgrExtMouseMode = "\x1b[?1006l"
|
ResetModeMouseExtSgr = "\x1b[?1006l"
|
||||||
RequestSgrExtMouseMode = "\x1b[?1006$p"
|
RequestModeMouseExtSgr = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UTF-8 Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
Utf8ExtMouseMode = DECMode(1005)
|
ModeMouseExtUtf8 = DECMode(1005)
|
||||||
|
|
||||||
SetUtf8ExtMouseMode = "\x1b[?1005h"
|
SetModeMouseExtUtf8 = "\x1b[?1005h"
|
||||||
ResetUtf8ExtMouseMode = "\x1b[?1005l"
|
ResetModeMouseExtUtf8 = "\x1b[?1005l"
|
||||||
RequestUtf8ExtMouseMode = "\x1b[?1005$p"
|
RequestModeMouseExtUtf8 = "\x1b[?1005$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// URXVT Extended Mouse Mode is a mode that changes the mouse tracking encoding
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
UrxvtExtMouseMode = DECMode(1015)
|
ModeMouseExtUrxvt = DECMode(1015)
|
||||||
|
|
||||||
SetUrxvtExtMouseMode = "\x1b[?1015h"
|
SetModeMouseExtUrxvt = "\x1b[?1015h"
|
||||||
ResetUrxvtExtMouseMode = "\x1b[?1015l"
|
ResetModeMouseExtUrxvt = "\x1b[?1015l"
|
||||||
RequestUrxvtExtMouseMode = "\x1b[?1015$p"
|
RequestModeMouseExtUrxvt = "\x1b[?1015$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SGR Pixel Extended Mouse Mode is a mode that changes the mouse tracking
|
// SGR Pixel Extended Mouse Mode is a mode that changes the mouse tracking
|
||||||
// encoding to use SGR parameters with pixel coordinates.
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
const (
|
const (
|
||||||
SgrPixelExtMouseMode = DECMode(1016)
|
ModeMouseExtSgrPixel = DECMode(1016)
|
||||||
|
|
||||||
SetSgrPixelExtMouseMode = "\x1b[?1016h"
|
SetModeMouseExtSgrPixel = "\x1b[?1016h"
|
||||||
ResetSgrPixelExtMouseMode = "\x1b[?1016l"
|
ResetModeMouseExtSgrPixel = "\x1b[?1016l"
|
||||||
RequestSgrPixelExtMouseMode = "\x1b[?1016$p"
|
RequestModeMouseExtSgrPixel = "\x1b[?1016$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Alternate Screen Mode is a mode that determines whether the alternate screen
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||||
const (
|
const (
|
||||||
AltScreenMode = DECMode(1047)
|
ModeAltScreen = DECMode(1047)
|
||||||
|
|
||||||
SetAltScreenMode = "\x1b[?1047h"
|
SetModeAltScreen = "\x1b[?1047h"
|
||||||
ResetAltScreenMode = "\x1b[?1047l"
|
ResetModeAltScreen = "\x1b[?1047l"
|
||||||
RequestAltScreenMode = "\x1b[?1047$p"
|
RequestModeAltScreen = "\x1b[?1047$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Save Cursor Mode is a mode that saves the cursor position.
|
// 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
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||||
const (
|
const (
|
||||||
SaveCursorMode = DECMode(1048)
|
ModeSaveCursor = DECMode(1048)
|
||||||
|
|
||||||
SetSaveCursorMode = "\x1b[?1048h"
|
SetModeSaveCursor = "\x1b[?1048h"
|
||||||
ResetSaveCursorMode = "\x1b[?1048l"
|
ResetModeSaveCursor = "\x1b[?1048l"
|
||||||
RequestSaveCursorMode = "\x1b[?1048$p"
|
RequestModeSaveCursor = "\x1b[?1048$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Alternate Screen Save Cursor Mode is a mode that saves the cursor position as in
|
// 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.
|
// and clears the screen on switch.
|
||||||
//
|
//
|
||||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
||||||
const (
|
const (
|
||||||
AltScreenSaveCursorMode = DECMode(1049)
|
ModeAltScreenSaveCursor = DECMode(1049)
|
||||||
|
|
||||||
SetAltScreenSaveCursorMode = "\x1b[?1049h"
|
SetModeAltScreenSaveCursor = "\x1b[?1049h"
|
||||||
ResetAltScreenSaveCursorMode = "\x1b[?1049l"
|
ResetModeAltScreenSaveCursor = "\x1b[?1049l"
|
||||||
RequestAltScreenSaveCursorMode = "\x1b[?1049$p"
|
RequestModeAltScreenSaveCursor = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bracketed Paste Mode is a mode that determines whether pasted text is
|
// 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://cirw.in/blog/bracketed-paste
|
||||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
|
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
|
||||||
const (
|
const (
|
||||||
BracketedPasteMode = DECMode(2004)
|
ModeBracketedPaste = DECMode(2004)
|
||||||
|
|
||||||
SetBracketedPasteMode = "\x1b[?2004h"
|
SetModeBracketedPaste = "\x1b[?2004h"
|
||||||
ResetBracketedPasteMode = "\x1b[?2004l"
|
ResetModeBracketedPaste = "\x1b[?2004l"
|
||||||
RequestBracketedPasteMode = "\x1b[?2004$p"
|
RequestModeBracketedPaste = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Synchronized Output Mode is a mode that determines whether output is
|
// Synchronized Output Mode is a mode that determines whether output is
|
||||||
@ -729,23 +617,11 @@ const (
|
|||||||
//
|
//
|
||||||
// See: https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036
|
// See: https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036
|
||||||
const (
|
const (
|
||||||
SynchronizedOutputMode = DECMode(2026)
|
ModeSynchronizedOutput = DECMode(2026)
|
||||||
|
|
||||||
SetSynchronizedOutputMode = "\x1b[?2026h"
|
SetModeSynchronizedOutput = "\x1b[?2026h"
|
||||||
ResetSynchronizedOutputMode = "\x1b[?2026l"
|
ResetModeSynchronizedOutput = "\x1b[?2026l"
|
||||||
RequestSynchronizedOutputMode = "\x1b[?2026$p"
|
RequestModeSynchronizedOutput = "\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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Unicode Core Mode is a mode that determines whether the terminal should use
|
// 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
|
// See: https://github.com/contour-terminal/terminal-unicode-core
|
||||||
const (
|
const (
|
||||||
UnicodeCoreMode = DECMode(2027)
|
ModeUnicodeCore = DECMode(2027)
|
||||||
|
|
||||||
SetUnicodeCoreMode = "\x1b[?2027h"
|
SetModeUnicodeCore = "\x1b[?2027h"
|
||||||
ResetUnicodeCoreMode = "\x1b[?2027l"
|
ResetModeUnicodeCore = "\x1b[?2027l"
|
||||||
RequestUnicodeCoreMode = "\x1b[?2027$p"
|
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"
|
// ModeLightDark is a mode that enables reporting the operating system's color
|
||||||
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
|
|
||||||
// scheme (light or dark) preference. It reports the color scheme as a [DSR]
|
// scheme (light or dark) preference. It reports the color scheme as a [DSR]
|
||||||
// and [LightDarkReport] escape sequences encoded as follows:
|
// and [LightDarkReport] escape sequences encoded as follows:
|
||||||
//
|
//
|
||||||
@ -802,14 +653,14 @@ const (
|
|||||||
//
|
//
|
||||||
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
||||||
const (
|
const (
|
||||||
LightDarkMode = DECMode(2031)
|
ModeLightDark = DECMode(2031)
|
||||||
|
|
||||||
SetLightDarkMode = "\x1b[?2031h"
|
SetModeLightDark = "\x1b[?2031h"
|
||||||
ResetLightDarkMode = "\x1b[?2031l"
|
ResetModeLightDark = "\x1b[?2031l"
|
||||||
RequestLightDarkMode = "\x1b[?2031$p"
|
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
|
// sequences. This is useful for systems that do not support [SIGWINCH] like
|
||||||
// Windows.
|
// Windows.
|
||||||
//
|
//
|
||||||
@ -819,11 +670,11 @@ const (
|
|||||||
//
|
//
|
||||||
// See: https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
|
// See: https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
|
||||||
const (
|
const (
|
||||||
InBandResizeMode = DECMode(2048)
|
ModeInBandResize = DECMode(2048)
|
||||||
|
|
||||||
SetInBandResizeMode = "\x1b[?2048h"
|
SetModeInBandResize = "\x1b[?2048h"
|
||||||
ResetInBandResizeMode = "\x1b[?2048l"
|
ResetModeInBandResize = "\x1b[?2048l"
|
||||||
RequestInBandResizeMode = "\x1b[?2048$p"
|
RequestModeInBandResize = "\x1b[?2048$p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Win32Input is a mode that determines whether input is processed by the
|
// 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
|
// See: https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md
|
||||||
const (
|
const (
|
||||||
Win32InputMode = DECMode(9001)
|
ModeWin32Input = DECMode(9001)
|
||||||
|
|
||||||
SetWin32InputMode = "\x1b[?9001h"
|
SetModeWin32Input = "\x1b[?9001h"
|
||||||
ResetWin32InputMode = "\x1b[?9001l"
|
ResetModeWin32Input = "\x1b[?9001l"
|
||||||
RequestWin32InputMode = "\x1b[?9001$p"
|
RequestModeWin32Input = "\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"
|
|
||||||
)
|
)
|
||||||
|
|||||||
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
|
m |= bitMotion
|
||||||
}
|
}
|
||||||
|
|
||||||
return //nolint:nakedret
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// x10Offset is the offset for X10 mouse events.
|
// 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
|
package ansi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Notify sends a desktop notification using iTerm's OSC 9.
|
// Notify sends a desktop notification using iTerm's OSC 9.
|
||||||
//
|
//
|
||||||
// OSC 9 ; Mc ST
|
// OSC 9 ; Mc ST
|
||||||
@ -11,3 +16,17 @@ package ansi
|
|||||||
func Notify(s string) string {
|
func Notify(s string) string {
|
||||||
return "\x1b]9;" + s + "\x07"
|
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,9 @@ import (
|
|||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/charmbracelet/x/ansi/parser"
|
"github.com/charmbracelet/x/ansi/parser"
|
||||||
|
"github.com/clipperhouse/displaywidth"
|
||||||
|
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
"github.com/rivo/uniseg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// State represents the state of the ANSI escape sequence parser used by
|
// State represents the state of the ANSI escape sequence parser used by
|
||||||
@ -176,10 +177,7 @@ func decodeSequence[T string | []byte](m Method, b T, state State, p *Parser) (s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if utf8.RuneStart(c) {
|
if utf8.RuneStart(c) {
|
||||||
seq, _, width, _ = FirstGraphemeCluster(b, -1)
|
seq, width = FirstGraphemeCluster(b, m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(seq))
|
|
||||||
}
|
|
||||||
i += len(seq)
|
i += len(seq)
|
||||||
return b[:i], width, i, NormalState
|
return b[:i], width, i, NormalState
|
||||||
}
|
}
|
||||||
@ -434,17 +432,22 @@ func HasEscPrefix[T string | []byte](b T) bool {
|
|||||||
return len(b) > 0 && b[0] == ESC
|
return len(b) > 0 && b[0] == ESC
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstGraphemeCluster returns the first grapheme cluster in the given string or byte slice.
|
// FirstGraphemeCluster returns the first grapheme cluster in the given string
|
||||||
// This is a syntactic sugar function that wraps
|
// or byte slice, and its monospace display width.
|
||||||
// uniseg.FirstGraphemeClusterInString and uniseg.FirstGraphemeCluster.
|
func FirstGraphemeCluster[T string | []byte](b T, m Method) (T, int) {
|
||||||
func FirstGraphemeCluster[T string | []byte](b T, state int) (T, T, int, int) {
|
|
||||||
switch b := any(b).(type) {
|
switch b := any(b).(type) {
|
||||||
case string:
|
case string:
|
||||||
cluster, rest, width, newState := uniseg.FirstGraphemeClusterInString(b, state)
|
cluster := graphemes.FromString(b).First()
|
||||||
return T(cluster), T(rest), width, newState
|
if m == WcWidth {
|
||||||
|
return T(cluster), runewidth.StringWidth(cluster)
|
||||||
|
}
|
||||||
|
return T(cluster), displaywidth.String(cluster)
|
||||||
case []byte:
|
case []byte:
|
||||||
cluster, rest, width, newState := uniseg.FirstGraphemeCluster(b, state)
|
cluster := graphemes.FromBytes(b).First()
|
||||||
return T(cluster), T(rest), width, newState
|
if m == WcWidth {
|
||||||
|
return T(cluster), runewidth.StringWidth(string(cluster))
|
||||||
|
}
|
||||||
|
return T(cluster), displaywidth.Bytes(cluster)
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
@ -490,7 +493,7 @@ func Command(prefix, inter, final byte) (c int) {
|
|||||||
c = int(final)
|
c = int(final)
|
||||||
c |= int(prefix) << parser.PrefixShift
|
c |= int(prefix) << parser.PrefixShift
|
||||||
c |= int(inter) << parser.IntermedShift
|
c |= int(inter) << parser.IntermedShift
|
||||||
return
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Param represents a sequence parameter. Sequence parameters with
|
// Param represents a sequence parameter. Sequence parameters with
|
||||||
@ -520,5 +523,5 @@ func Parameter(p int, hasMore bool) (s int) {
|
|||||||
if hasMore {
|
if hasMore {
|
||||||
s |= parser.HasMoreFlag
|
s |= parser.HasMoreFlag
|
||||||
}
|
}
|
||||||
return
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
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{
|
var attrStrings = map[int]string{
|
||||||
ResetAttr: resetAttr,
|
AttrReset: attrReset,
|
||||||
BoldAttr: boldAttr,
|
AttrBold: attrBold,
|
||||||
FaintAttr: faintAttr,
|
AttrFaint: attrFaint,
|
||||||
ItalicAttr: italicAttr,
|
AttrItalic: attrItalic,
|
||||||
UnderlineAttr: underlineAttr,
|
AttrUnderline: attrUnderline,
|
||||||
SlowBlinkAttr: slowBlinkAttr,
|
AttrBlink: attrBlink,
|
||||||
RapidBlinkAttr: rapidBlinkAttr,
|
AttrRapidBlink: attrRapidBlink,
|
||||||
ReverseAttr: reverseAttr,
|
AttrReverse: attrReverse,
|
||||||
ConcealAttr: concealAttr,
|
AttrConceal: attrConceal,
|
||||||
StrikethroughAttr: strikethroughAttr,
|
AttrStrikethrough: attrStrikethrough,
|
||||||
NormalIntensityAttr: normalIntensityAttr,
|
AttrNormalIntensity: attrNormalIntensity,
|
||||||
NoItalicAttr: noItalicAttr,
|
AttrNoItalic: attrNoItalic,
|
||||||
NoUnderlineAttr: noUnderlineAttr,
|
AttrNoUnderline: attrNoUnderline,
|
||||||
NoBlinkAttr: noBlinkAttr,
|
AttrNoBlink: attrNoBlink,
|
||||||
NoReverseAttr: noReverseAttr,
|
AttrNoReverse: attrNoReverse,
|
||||||
NoConcealAttr: noConcealAttr,
|
AttrNoConceal: attrNoConceal,
|
||||||
NoStrikethroughAttr: noStrikethroughAttr,
|
AttrNoStrikethrough: attrNoStrikethrough,
|
||||||
BlackForegroundColorAttr: blackForegroundColorAttr,
|
AttrBlackForegroundColor: attrBlackForegroundColor,
|
||||||
RedForegroundColorAttr: redForegroundColorAttr,
|
AttrRedForegroundColor: attrRedForegroundColor,
|
||||||
GreenForegroundColorAttr: greenForegroundColorAttr,
|
AttrGreenForegroundColor: attrGreenForegroundColor,
|
||||||
YellowForegroundColorAttr: yellowForegroundColorAttr,
|
AttrYellowForegroundColor: attrYellowForegroundColor,
|
||||||
BlueForegroundColorAttr: blueForegroundColorAttr,
|
AttrBlueForegroundColor: attrBlueForegroundColor,
|
||||||
MagentaForegroundColorAttr: magentaForegroundColorAttr,
|
AttrMagentaForegroundColor: attrMagentaForegroundColor,
|
||||||
CyanForegroundColorAttr: cyanForegroundColorAttr,
|
AttrCyanForegroundColor: attrCyanForegroundColor,
|
||||||
WhiteForegroundColorAttr: whiteForegroundColorAttr,
|
AttrWhiteForegroundColor: attrWhiteForegroundColor,
|
||||||
ExtendedForegroundColorAttr: extendedForegroundColorAttr,
|
AttrExtendedForegroundColor: attrExtendedForegroundColor,
|
||||||
DefaultForegroundColorAttr: defaultForegroundColorAttr,
|
AttrDefaultForegroundColor: attrDefaultForegroundColor,
|
||||||
BlackBackgroundColorAttr: blackBackgroundColorAttr,
|
AttrBlackBackgroundColor: attrBlackBackgroundColor,
|
||||||
RedBackgroundColorAttr: redBackgroundColorAttr,
|
AttrRedBackgroundColor: attrRedBackgroundColor,
|
||||||
GreenBackgroundColorAttr: greenBackgroundColorAttr,
|
AttrGreenBackgroundColor: attrGreenBackgroundColor,
|
||||||
YellowBackgroundColorAttr: yellowBackgroundColorAttr,
|
AttrYellowBackgroundColor: attrYellowBackgroundColor,
|
||||||
BlueBackgroundColorAttr: blueBackgroundColorAttr,
|
AttrBlueBackgroundColor: attrBlueBackgroundColor,
|
||||||
MagentaBackgroundColorAttr: magentaBackgroundColorAttr,
|
AttrMagentaBackgroundColor: attrMagentaBackgroundColor,
|
||||||
CyanBackgroundColorAttr: cyanBackgroundColorAttr,
|
AttrCyanBackgroundColor: attrCyanBackgroundColor,
|
||||||
WhiteBackgroundColorAttr: whiteBackgroundColorAttr,
|
AttrWhiteBackgroundColor: attrWhiteBackgroundColor,
|
||||||
ExtendedBackgroundColorAttr: extendedBackgroundColorAttr,
|
AttrExtendedBackgroundColor: attrExtendedBackgroundColor,
|
||||||
DefaultBackgroundColorAttr: defaultBackgroundColorAttr,
|
AttrDefaultBackgroundColor: attrDefaultBackgroundColor,
|
||||||
ExtendedUnderlineColorAttr: extendedUnderlineColorAttr,
|
AttrExtendedUnderlineColor: attrExtendedUnderlineColor,
|
||||||
DefaultUnderlineColorAttr: defaultUnderlineColorAttr,
|
AttrDefaultUnderlineColor: attrDefaultUnderlineColor,
|
||||||
BrightBlackForegroundColorAttr: brightBlackForegroundColorAttr,
|
AttrBrightBlackForegroundColor: attrBrightBlackForegroundColor,
|
||||||
BrightRedForegroundColorAttr: brightRedForegroundColorAttr,
|
AttrBrightRedForegroundColor: attrBrightRedForegroundColor,
|
||||||
BrightGreenForegroundColorAttr: brightGreenForegroundColorAttr,
|
AttrBrightGreenForegroundColor: attrBrightGreenForegroundColor,
|
||||||
BrightYellowForegroundColorAttr: brightYellowForegroundColorAttr,
|
AttrBrightYellowForegroundColor: attrBrightYellowForegroundColor,
|
||||||
BrightBlueForegroundColorAttr: brightBlueForegroundColorAttr,
|
AttrBrightBlueForegroundColor: attrBrightBlueForegroundColor,
|
||||||
BrightMagentaForegroundColorAttr: brightMagentaForegroundColorAttr,
|
AttrBrightMagentaForegroundColor: attrBrightMagentaForegroundColor,
|
||||||
BrightCyanForegroundColorAttr: brightCyanForegroundColorAttr,
|
AttrBrightCyanForegroundColor: attrBrightCyanForegroundColor,
|
||||||
BrightWhiteForegroundColorAttr: brightWhiteForegroundColorAttr,
|
AttrBrightWhiteForegroundColor: attrBrightWhiteForegroundColor,
|
||||||
BrightBlackBackgroundColorAttr: brightBlackBackgroundColorAttr,
|
AttrBrightBlackBackgroundColor: attrBrightBlackBackgroundColor,
|
||||||
BrightRedBackgroundColorAttr: brightRedBackgroundColorAttr,
|
AttrBrightRedBackgroundColor: attrBrightRedBackgroundColor,
|
||||||
BrightGreenBackgroundColorAttr: brightGreenBackgroundColorAttr,
|
AttrBrightGreenBackgroundColor: attrBrightGreenBackgroundColor,
|
||||||
BrightYellowBackgroundColorAttr: brightYellowBackgroundColorAttr,
|
AttrBrightYellowBackgroundColor: attrBrightYellowBackgroundColor,
|
||||||
BrightBlueBackgroundColorAttr: brightBlueBackgroundColorAttr,
|
AttrBrightBlueBackgroundColor: attrBrightBlueBackgroundColor,
|
||||||
BrightMagentaBackgroundColorAttr: brightMagentaBackgroundColorAttr,
|
AttrBrightMagentaBackgroundColor: attrBrightMagentaBackgroundColor,
|
||||||
BrightCyanBackgroundColorAttr: brightCyanBackgroundColorAttr,
|
AttrBrightCyanBackgroundColor: attrBrightCyanBackgroundColor,
|
||||||
BrightWhiteBackgroundColorAttr: brightWhiteBackgroundColorAttr,
|
AttrBrightWhiteBackgroundColor: attrBrightWhiteBackgroundColor,
|
||||||
}
|
}
|
||||||
|
|||||||
603
vendor/github.com/charmbracelet/x/ansi/style.go
generated
vendored
603
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.
|
// Style represents an ANSI SGR (Select Graphic Rendition) style.
|
||||||
type Style []string
|
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 {
|
func NewStyle(attrs ...Attr) Style {
|
||||||
if len(attrs) == 0 {
|
if len(attrs) == 0 {
|
||||||
return Style{}
|
return Style{}
|
||||||
@ -46,7 +48,8 @@ func (s Style) String() string {
|
|||||||
return "\x1b[" + strings.Join(s, ";") + "m"
|
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 {
|
func (s Style) Styled(str string) string {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return str
|
return str
|
||||||
@ -54,161 +57,211 @@ func (s Style) Styled(str string) string {
|
|||||||
return s.String() + str + ResetStyle
|
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 {
|
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 {
|
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 {
|
func (s Style) Faint() Style {
|
||||||
return append(s, faintAttr)
|
return append(s, attrFaint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Italic appends the italic style attribute to the style.
|
// Italic appends the italic or no italic style attribute to the style.
|
||||||
func (s Style) Italic() Style {
|
// When v is true, text is rendered in italic. When false, italic is disabled.
|
||||||
return append(s, italicAttr)
|
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.
|
// Underline appends the underline or no underline style attribute to the style.
|
||||||
func (s Style) Underline() Style {
|
// When v is true, text is underlined. When false, underline is disabled.
|
||||||
return append(s, underlineAttr)
|
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.
|
// UnderlineStyle appends the underline style attribute to the style.
|
||||||
|
// Supports various underline styles including single, double, curly, dotted,
|
||||||
|
// and dashed.
|
||||||
func (s Style) UnderlineStyle(u UnderlineStyle) Style {
|
func (s Style) UnderlineStyle(u UnderlineStyle) Style {
|
||||||
switch u {
|
switch u {
|
||||||
case NoUnderlineStyle:
|
case UnderlineStyleNone:
|
||||||
return s.NoUnderline()
|
return s.Underline(false)
|
||||||
case SingleUnderlineStyle:
|
case UnderlineStyleSingle:
|
||||||
return s.Underline()
|
return s.Underline(true)
|
||||||
case DoubleUnderlineStyle:
|
case UnderlineStyleDouble:
|
||||||
return append(s, doubleUnderlineStyle)
|
return append(s, underlineStyleDouble)
|
||||||
case CurlyUnderlineStyle:
|
case UnderlineStyleCurly:
|
||||||
return append(s, curlyUnderlineStyle)
|
return append(s, underlineStyleCurly)
|
||||||
case DottedUnderlineStyle:
|
case UnderlineStyleDotted:
|
||||||
return append(s, dottedUnderlineStyle)
|
return append(s, underlineStyleDotted)
|
||||||
case DashedUnderlineStyle:
|
case UnderlineStyleDashed:
|
||||||
return append(s, dashedUnderlineStyle)
|
return append(s, underlineStyleDashed)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoubleUnderline appends the double underline style attribute to the style.
|
// Blink appends the slow blink or no blink style attribute to the style.
|
||||||
// This is a convenience method for UnderlineStyle(DoubleUnderlineStyle).
|
// When v is true, text blinks slowly (less than 150 per minute). When false,
|
||||||
func (s Style) DoubleUnderline() Style {
|
// blinking is disabled.
|
||||||
return s.UnderlineStyle(DoubleUnderlineStyle)
|
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.
|
// RapidBlink appends the rapid blink or no blink style attribute to the style.
|
||||||
// This is a convenience method for UnderlineStyle(CurlyUnderlineStyle).
|
// When v is true, text blinks rapidly (150+ per minute). When false, blinking
|
||||||
func (s Style) CurlyUnderline() Style {
|
// is disabled.
|
||||||
return s.UnderlineStyle(CurlyUnderlineStyle)
|
//
|
||||||
|
// 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.
|
// Reverse appends the reverse or no reverse style attribute to the style.
|
||||||
// This is a convenience method for UnderlineStyle(DottedUnderlineStyle).
|
// When v is true, foreground and background colors are swapped. When false,
|
||||||
func (s Style) DottedUnderline() Style {
|
// reverse video is disabled.
|
||||||
return s.UnderlineStyle(DottedUnderlineStyle)
|
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.
|
// Conceal appends the conceal or no conceal style attribute to the style.
|
||||||
// This is a convenience method for UnderlineStyle(DashedUnderlineStyle).
|
// When v is true, text is hidden/concealed. When false, concealment is
|
||||||
func (s Style) DashedUnderline() Style {
|
// disabled.
|
||||||
return s.UnderlineStyle(DashedUnderlineStyle)
|
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.
|
// Strikethrough appends the strikethrough or no strikethrough style attribute
|
||||||
func (s Style) SlowBlink() Style {
|
// to the style. When v is true, text is rendered with a horizontal line through
|
||||||
return append(s, slowBlinkAttr)
|
// 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.
|
// Normal appends the normal intensity style attribute to the style. This
|
||||||
func (s Style) RapidBlink() Style {
|
// resets [Style.Bold] and [Style.Faint] attributes.
|
||||||
return append(s, rapidBlinkAttr)
|
func (s Style) Normal() Style {
|
||||||
}
|
return append(s, attrNormalIntensity)
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoItalic appends the no italic style attribute to the style.
|
// NoItalic appends the no italic style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.Italic](false) instead.
|
||||||
func (s Style) NoItalic() Style {
|
func (s Style) NoItalic() Style {
|
||||||
return append(s, noItalicAttr)
|
return append(s, attrNoItalic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoUnderline appends the no underline style attribute to the style.
|
// NoUnderline appends the no underline style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.Underline](false) instead.
|
||||||
func (s Style) NoUnderline() Style {
|
func (s Style) NoUnderline() Style {
|
||||||
return append(s, noUnderlineAttr)
|
return append(s, attrNoUnderline)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoBlink appends the no blink style attribute to the style.
|
// 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 {
|
func (s Style) NoBlink() Style {
|
||||||
return append(s, noBlinkAttr)
|
return append(s, attrNoBlink)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoReverse appends the no reverse style attribute to the style.
|
// NoReverse appends the no reverse style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.Reverse](false) instead.
|
||||||
func (s Style) NoReverse() Style {
|
func (s Style) NoReverse() Style {
|
||||||
return append(s, noReverseAttr)
|
return append(s, attrNoReverse)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoConceal appends the no conceal style attribute to the style.
|
// NoConceal appends the no conceal style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.Conceal](false) instead.
|
||||||
func (s Style) NoConceal() Style {
|
func (s Style) NoConceal() Style {
|
||||||
return append(s, noConcealAttr)
|
return append(s, attrNoConceal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoStrikethrough appends the no strikethrough style attribute to the style.
|
// NoStrikethrough appends the no strikethrough style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.Strikethrough](false) instead.
|
||||||
func (s Style) NoStrikethrough() Style {
|
func (s Style) NoStrikethrough() Style {
|
||||||
return append(s, noStrikethroughAttr)
|
return append(s, attrNoStrikethrough)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultForegroundColor appends the default foreground color style attribute to the style.
|
// DefaultForegroundColor appends the default foreground color style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.ForegroundColor](nil) instead.
|
||||||
func (s Style) DefaultForegroundColor() Style {
|
func (s Style) DefaultForegroundColor() Style {
|
||||||
return append(s, defaultForegroundColorAttr)
|
return append(s, attrDefaultForegroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultBackgroundColor appends the default background color style attribute to the style.
|
// DefaultBackgroundColor appends the default background color style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.BackgroundColor](nil) instead.
|
||||||
func (s Style) DefaultBackgroundColor() Style {
|
func (s Style) DefaultBackgroundColor() Style {
|
||||||
return append(s, defaultBackgroundColorAttr)
|
return append(s, attrDefaultBackgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultUnderlineColor appends the default underline color style attribute to the style.
|
// DefaultUnderlineColor appends the default underline color style attribute to the style.
|
||||||
|
//
|
||||||
|
// Deprecated: use [Style.UnderlineColor](nil) instead.
|
||||||
func (s Style) DefaultUnderlineColor() Style {
|
func (s Style) DefaultUnderlineColor() Style {
|
||||||
return append(s, defaultUnderlineColorAttr)
|
return append(s, attrDefaultUnderlineColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForegroundColor appends the foreground color style attribute to the style.
|
// 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 {
|
func (s Style) ForegroundColor(c Color) Style {
|
||||||
|
if c == nil {
|
||||||
|
return append(s, attrDefaultForegroundColor)
|
||||||
|
}
|
||||||
return append(s, foregroundColorString(c))
|
return append(s, foregroundColorString(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackgroundColor appends the background color style attribute to the style.
|
// 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 {
|
func (s Style) BackgroundColor(c Color) Style {
|
||||||
|
if c == nil {
|
||||||
|
return append(s, attrDefaultBackgroundColor)
|
||||||
|
}
|
||||||
return append(s, backgroundColorString(c))
|
return append(s, backgroundColorString(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnderlineColor appends the underline color style attribute to the style.
|
// 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 {
|
func (s Style) UnderlineColor(c Color) Style {
|
||||||
|
if c == nil {
|
||||||
|
return append(s, attrDefaultUnderlineColor)
|
||||||
|
}
|
||||||
return append(s, underlineColorString(c))
|
return append(s, underlineColorString(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,146 +270,216 @@ func (s Style) UnderlineColor(c Color) Style {
|
|||||||
type UnderlineStyle = byte
|
type UnderlineStyle = byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
doubleUnderlineStyle = "4:2"
|
underlineStyleDouble = "4:2"
|
||||||
curlyUnderlineStyle = "4:3"
|
underlineStyleCurly = "4:3"
|
||||||
dottedUnderlineStyle = "4:4"
|
underlineStyleDotted = "4:4"
|
||||||
dashedUnderlineStyle = "4:5"
|
underlineStyleDashed = "4:5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Underline styles constants.
|
||||||
|
const (
|
||||||
|
UnderlineStyleNone UnderlineStyle = iota
|
||||||
|
UnderlineStyleSingle
|
||||||
|
UnderlineStyleDouble
|
||||||
|
UnderlineStyleCurly
|
||||||
|
UnderlineStyleDotted
|
||||||
|
UnderlineStyleDashed
|
||||||
|
)
|
||||||
|
|
||||||
|
// Underline styles constants.
|
||||||
|
//
|
||||||
|
// Deprecated: use [UnderlineStyleNone], [UnderlineStyleSingle], etc. instead.
|
||||||
const (
|
const (
|
||||||
// NoUnderlineStyle is the default underline style.
|
|
||||||
NoUnderlineStyle UnderlineStyle = iota
|
NoUnderlineStyle UnderlineStyle = iota
|
||||||
// SingleUnderlineStyle is a single underline style.
|
|
||||||
SingleUnderlineStyle
|
SingleUnderlineStyle
|
||||||
// DoubleUnderlineStyle is a double underline style.
|
|
||||||
DoubleUnderlineStyle
|
DoubleUnderlineStyle
|
||||||
// CurlyUnderlineStyle is a curly underline style.
|
|
||||||
CurlyUnderlineStyle
|
CurlyUnderlineStyle
|
||||||
// DottedUnderlineStyle is a dotted underline style.
|
|
||||||
DottedUnderlineStyle
|
DottedUnderlineStyle
|
||||||
// DashedUnderlineStyle is a dashed underline style.
|
|
||||||
DashedUnderlineStyle
|
DashedUnderlineStyle
|
||||||
)
|
)
|
||||||
|
|
||||||
// SGR (Select Graphic Rendition) style attributes.
|
// SGR (Select Graphic Rendition) style attributes.
|
||||||
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
||||||
const (
|
const (
|
||||||
ResetAttr Attr = 0
|
AttrReset Attr = 0
|
||||||
BoldAttr Attr = 1
|
AttrBold Attr = 1
|
||||||
FaintAttr Attr = 2
|
AttrFaint Attr = 2
|
||||||
ItalicAttr Attr = 3
|
AttrItalic Attr = 3
|
||||||
UnderlineAttr Attr = 4
|
AttrUnderline Attr = 4
|
||||||
SlowBlinkAttr Attr = 5
|
AttrBlink Attr = 5
|
||||||
RapidBlinkAttr Attr = 6
|
AttrRapidBlink Attr = 6
|
||||||
ReverseAttr Attr = 7
|
AttrReverse Attr = 7
|
||||||
ConcealAttr Attr = 8
|
AttrConceal Attr = 8
|
||||||
StrikethroughAttr Attr = 9
|
AttrStrikethrough Attr = 9
|
||||||
NormalIntensityAttr Attr = 22
|
AttrNormalIntensity Attr = 22
|
||||||
NoItalicAttr Attr = 23
|
AttrNoItalic Attr = 23
|
||||||
NoUnderlineAttr Attr = 24
|
AttrNoUnderline Attr = 24
|
||||||
NoBlinkAttr Attr = 25
|
AttrNoBlink Attr = 25
|
||||||
NoReverseAttr Attr = 27
|
AttrNoReverse Attr = 27
|
||||||
NoConcealAttr Attr = 28
|
AttrNoConceal Attr = 28
|
||||||
NoStrikethroughAttr Attr = 29
|
AttrNoStrikethrough Attr = 29
|
||||||
BlackForegroundColorAttr Attr = 30
|
AttrBlackForegroundColor Attr = 30
|
||||||
RedForegroundColorAttr Attr = 31
|
AttrRedForegroundColor Attr = 31
|
||||||
GreenForegroundColorAttr Attr = 32
|
AttrGreenForegroundColor Attr = 32
|
||||||
YellowForegroundColorAttr Attr = 33
|
AttrYellowForegroundColor Attr = 33
|
||||||
BlueForegroundColorAttr Attr = 34
|
AttrBlueForegroundColor Attr = 34
|
||||||
MagentaForegroundColorAttr Attr = 35
|
AttrMagentaForegroundColor Attr = 35
|
||||||
CyanForegroundColorAttr Attr = 36
|
AttrCyanForegroundColor Attr = 36
|
||||||
WhiteForegroundColorAttr Attr = 37
|
AttrWhiteForegroundColor Attr = 37
|
||||||
ExtendedForegroundColorAttr Attr = 38
|
AttrExtendedForegroundColor Attr = 38
|
||||||
DefaultForegroundColorAttr Attr = 39
|
AttrDefaultForegroundColor Attr = 39
|
||||||
BlackBackgroundColorAttr Attr = 40
|
AttrBlackBackgroundColor Attr = 40
|
||||||
RedBackgroundColorAttr Attr = 41
|
AttrRedBackgroundColor Attr = 41
|
||||||
GreenBackgroundColorAttr Attr = 42
|
AttrGreenBackgroundColor Attr = 42
|
||||||
YellowBackgroundColorAttr Attr = 43
|
AttrYellowBackgroundColor Attr = 43
|
||||||
BlueBackgroundColorAttr Attr = 44
|
AttrBlueBackgroundColor Attr = 44
|
||||||
MagentaBackgroundColorAttr Attr = 45
|
AttrMagentaBackgroundColor Attr = 45
|
||||||
CyanBackgroundColorAttr Attr = 46
|
AttrCyanBackgroundColor Attr = 46
|
||||||
WhiteBackgroundColorAttr Attr = 47
|
AttrWhiteBackgroundColor Attr = 47
|
||||||
ExtendedBackgroundColorAttr Attr = 48
|
AttrExtendedBackgroundColor Attr = 48
|
||||||
DefaultBackgroundColorAttr Attr = 49
|
AttrDefaultBackgroundColor Attr = 49
|
||||||
ExtendedUnderlineColorAttr Attr = 58
|
AttrExtendedUnderlineColor Attr = 58
|
||||||
DefaultUnderlineColorAttr Attr = 59
|
AttrDefaultUnderlineColor Attr = 59
|
||||||
BrightBlackForegroundColorAttr Attr = 90
|
AttrBrightBlackForegroundColor Attr = 90
|
||||||
BrightRedForegroundColorAttr Attr = 91
|
AttrBrightRedForegroundColor Attr = 91
|
||||||
BrightGreenForegroundColorAttr Attr = 92
|
AttrBrightGreenForegroundColor Attr = 92
|
||||||
BrightYellowForegroundColorAttr Attr = 93
|
AttrBrightYellowForegroundColor Attr = 93
|
||||||
BrightBlueForegroundColorAttr Attr = 94
|
AttrBrightBlueForegroundColor Attr = 94
|
||||||
BrightMagentaForegroundColorAttr Attr = 95
|
AttrBrightMagentaForegroundColor Attr = 95
|
||||||
BrightCyanForegroundColorAttr Attr = 96
|
AttrBrightCyanForegroundColor Attr = 96
|
||||||
BrightWhiteForegroundColorAttr Attr = 97
|
AttrBrightWhiteForegroundColor Attr = 97
|
||||||
BrightBlackBackgroundColorAttr Attr = 100
|
AttrBrightBlackBackgroundColor Attr = 100
|
||||||
BrightRedBackgroundColorAttr Attr = 101
|
AttrBrightRedBackgroundColor Attr = 101
|
||||||
BrightGreenBackgroundColorAttr Attr = 102
|
AttrBrightGreenBackgroundColor Attr = 102
|
||||||
BrightYellowBackgroundColorAttr Attr = 103
|
AttrBrightYellowBackgroundColor Attr = 103
|
||||||
BrightBlueBackgroundColorAttr Attr = 104
|
AttrBrightBlueBackgroundColor Attr = 104
|
||||||
BrightMagentaBackgroundColorAttr Attr = 105
|
AttrBrightMagentaBackgroundColor Attr = 105
|
||||||
BrightCyanBackgroundColorAttr Attr = 106
|
AttrBrightCyanBackgroundColor Attr = 106
|
||||||
BrightWhiteBackgroundColorAttr Attr = 107
|
AttrBrightWhiteBackgroundColor Attr = 107
|
||||||
|
|
||||||
RGBColorIntroducerAttr Attr = 2
|
AttrRGBColorIntroducer Attr = 2
|
||||||
ExtendedColorIntroducerAttr Attr = 5
|
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 (
|
const (
|
||||||
resetAttr = "0"
|
attrReset = "0"
|
||||||
boldAttr = "1"
|
attrBold = "1"
|
||||||
faintAttr = "2"
|
attrFaint = "2"
|
||||||
italicAttr = "3"
|
attrItalic = "3"
|
||||||
underlineAttr = "4"
|
attrUnderline = "4"
|
||||||
slowBlinkAttr = "5"
|
attrBlink = "5"
|
||||||
rapidBlinkAttr = "6"
|
attrRapidBlink = "6"
|
||||||
reverseAttr = "7"
|
attrReverse = "7"
|
||||||
concealAttr = "8"
|
attrConceal = "8"
|
||||||
strikethroughAttr = "9"
|
attrStrikethrough = "9"
|
||||||
normalIntensityAttr = "22"
|
attrNormalIntensity = "22"
|
||||||
noItalicAttr = "23"
|
attrNoItalic = "23"
|
||||||
noUnderlineAttr = "24"
|
attrNoUnderline = "24"
|
||||||
noBlinkAttr = "25"
|
attrNoBlink = "25"
|
||||||
noReverseAttr = "27"
|
attrNoReverse = "27"
|
||||||
noConcealAttr = "28"
|
attrNoConceal = "28"
|
||||||
noStrikethroughAttr = "29"
|
attrNoStrikethrough = "29"
|
||||||
blackForegroundColorAttr = "30"
|
attrBlackForegroundColor = "30"
|
||||||
redForegroundColorAttr = "31"
|
attrRedForegroundColor = "31"
|
||||||
greenForegroundColorAttr = "32"
|
attrGreenForegroundColor = "32"
|
||||||
yellowForegroundColorAttr = "33"
|
attrYellowForegroundColor = "33"
|
||||||
blueForegroundColorAttr = "34"
|
attrBlueForegroundColor = "34"
|
||||||
magentaForegroundColorAttr = "35"
|
attrMagentaForegroundColor = "35"
|
||||||
cyanForegroundColorAttr = "36"
|
attrCyanForegroundColor = "36"
|
||||||
whiteForegroundColorAttr = "37"
|
attrWhiteForegroundColor = "37"
|
||||||
extendedForegroundColorAttr = "38"
|
attrExtendedForegroundColor = "38"
|
||||||
defaultForegroundColorAttr = "39"
|
attrDefaultForegroundColor = "39"
|
||||||
blackBackgroundColorAttr = "40"
|
attrBlackBackgroundColor = "40"
|
||||||
redBackgroundColorAttr = "41"
|
attrRedBackgroundColor = "41"
|
||||||
greenBackgroundColorAttr = "42"
|
attrGreenBackgroundColor = "42"
|
||||||
yellowBackgroundColorAttr = "43"
|
attrYellowBackgroundColor = "43"
|
||||||
blueBackgroundColorAttr = "44"
|
attrBlueBackgroundColor = "44"
|
||||||
magentaBackgroundColorAttr = "45"
|
attrMagentaBackgroundColor = "45"
|
||||||
cyanBackgroundColorAttr = "46"
|
attrCyanBackgroundColor = "46"
|
||||||
whiteBackgroundColorAttr = "47"
|
attrWhiteBackgroundColor = "47"
|
||||||
extendedBackgroundColorAttr = "48"
|
attrExtendedBackgroundColor = "48"
|
||||||
defaultBackgroundColorAttr = "49"
|
attrDefaultBackgroundColor = "49"
|
||||||
extendedUnderlineColorAttr = "58"
|
attrExtendedUnderlineColor = "58"
|
||||||
defaultUnderlineColorAttr = "59"
|
attrDefaultUnderlineColor = "59"
|
||||||
brightBlackForegroundColorAttr = "90"
|
attrBrightBlackForegroundColor = "90"
|
||||||
brightRedForegroundColorAttr = "91"
|
attrBrightRedForegroundColor = "91"
|
||||||
brightGreenForegroundColorAttr = "92"
|
attrBrightGreenForegroundColor = "92"
|
||||||
brightYellowForegroundColorAttr = "93"
|
attrBrightYellowForegroundColor = "93"
|
||||||
brightBlueForegroundColorAttr = "94"
|
attrBrightBlueForegroundColor = "94"
|
||||||
brightMagentaForegroundColorAttr = "95"
|
attrBrightMagentaForegroundColor = "95"
|
||||||
brightCyanForegroundColorAttr = "96"
|
attrBrightCyanForegroundColor = "96"
|
||||||
brightWhiteForegroundColorAttr = "97"
|
attrBrightWhiteForegroundColor = "97"
|
||||||
brightBlackBackgroundColorAttr = "100"
|
attrBrightBlackBackgroundColor = "100"
|
||||||
brightRedBackgroundColorAttr = "101"
|
attrBrightRedBackgroundColor = "101"
|
||||||
brightGreenBackgroundColorAttr = "102"
|
attrBrightGreenBackgroundColor = "102"
|
||||||
brightYellowBackgroundColorAttr = "103"
|
attrBrightYellowBackgroundColor = "103"
|
||||||
brightBlueBackgroundColorAttr = "104"
|
attrBrightBlueBackgroundColor = "104"
|
||||||
brightMagentaBackgroundColorAttr = "105"
|
attrBrightMagentaBackgroundColor = "105"
|
||||||
brightCyanBackgroundColorAttr = "106"
|
attrBrightCyanBackgroundColor = "106"
|
||||||
brightWhiteBackgroundColorAttr = "107"
|
attrBrightWhiteBackgroundColor = "107"
|
||||||
)
|
)
|
||||||
|
|
||||||
// foregroundColorString returns the style SGR attribute for the given
|
// foregroundColorString returns the style SGR attribute for the given
|
||||||
@ -369,37 +492,37 @@ func foregroundColorString(c Color) string {
|
|||||||
// "3<n>" or "9<n>" where n is the color number from 0 to 7
|
// "3<n>" or "9<n>" where n is the color number from 0 to 7
|
||||||
switch c {
|
switch c {
|
||||||
case Black:
|
case Black:
|
||||||
return blackForegroundColorAttr
|
return attrBlackForegroundColor
|
||||||
case Red:
|
case Red:
|
||||||
return redForegroundColorAttr
|
return attrRedForegroundColor
|
||||||
case Green:
|
case Green:
|
||||||
return greenForegroundColorAttr
|
return attrGreenForegroundColor
|
||||||
case Yellow:
|
case Yellow:
|
||||||
return yellowForegroundColorAttr
|
return attrYellowForegroundColor
|
||||||
case Blue:
|
case Blue:
|
||||||
return blueForegroundColorAttr
|
return attrBlueForegroundColor
|
||||||
case Magenta:
|
case Magenta:
|
||||||
return magentaForegroundColorAttr
|
return attrMagentaForegroundColor
|
||||||
case Cyan:
|
case Cyan:
|
||||||
return cyanForegroundColorAttr
|
return attrCyanForegroundColor
|
||||||
case White:
|
case White:
|
||||||
return whiteForegroundColorAttr
|
return attrWhiteForegroundColor
|
||||||
case BrightBlack:
|
case BrightBlack:
|
||||||
return brightBlackForegroundColorAttr
|
return attrBrightBlackForegroundColor
|
||||||
case BrightRed:
|
case BrightRed:
|
||||||
return brightRedForegroundColorAttr
|
return attrBrightRedForegroundColor
|
||||||
case BrightGreen:
|
case BrightGreen:
|
||||||
return brightGreenForegroundColorAttr
|
return attrBrightGreenForegroundColor
|
||||||
case BrightYellow:
|
case BrightYellow:
|
||||||
return brightYellowForegroundColorAttr
|
return attrBrightYellowForegroundColor
|
||||||
case BrightBlue:
|
case BrightBlue:
|
||||||
return brightBlueForegroundColorAttr
|
return attrBrightBlueForegroundColor
|
||||||
case BrightMagenta:
|
case BrightMagenta:
|
||||||
return brightMagentaForegroundColorAttr
|
return attrBrightMagentaForegroundColor
|
||||||
case BrightCyan:
|
case BrightCyan:
|
||||||
return brightCyanForegroundColorAttr
|
return attrBrightCyanForegroundColor
|
||||||
case BrightWhite:
|
case BrightWhite:
|
||||||
return brightWhiteForegroundColorAttr
|
return attrBrightWhiteForegroundColor
|
||||||
}
|
}
|
||||||
case ExtendedColor:
|
case ExtendedColor:
|
||||||
// 256-color ANSI foreground
|
// 256-color ANSI foreground
|
||||||
@ -414,7 +537,7 @@ func foregroundColorString(c Color) string {
|
|||||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||||
strconv.FormatUint(uint64(shift(b)), 10)
|
strconv.FormatUint(uint64(shift(b)), 10)
|
||||||
}
|
}
|
||||||
return defaultForegroundColorAttr
|
return attrDefaultForegroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// backgroundColorString returns the style SGR attribute for the given
|
// backgroundColorString returns the style SGR attribute for the given
|
||||||
@ -427,37 +550,37 @@ func backgroundColorString(c Color) string {
|
|||||||
// "4<n>" or "10<n>" where n is the color number from 0 to 7
|
// "4<n>" or "10<n>" where n is the color number from 0 to 7
|
||||||
switch c {
|
switch c {
|
||||||
case Black:
|
case Black:
|
||||||
return blackBackgroundColorAttr
|
return attrBlackBackgroundColor
|
||||||
case Red:
|
case Red:
|
||||||
return redBackgroundColorAttr
|
return attrRedBackgroundColor
|
||||||
case Green:
|
case Green:
|
||||||
return greenBackgroundColorAttr
|
return attrGreenBackgroundColor
|
||||||
case Yellow:
|
case Yellow:
|
||||||
return yellowBackgroundColorAttr
|
return attrYellowBackgroundColor
|
||||||
case Blue:
|
case Blue:
|
||||||
return blueBackgroundColorAttr
|
return attrBlueBackgroundColor
|
||||||
case Magenta:
|
case Magenta:
|
||||||
return magentaBackgroundColorAttr
|
return attrMagentaBackgroundColor
|
||||||
case Cyan:
|
case Cyan:
|
||||||
return cyanBackgroundColorAttr
|
return attrCyanBackgroundColor
|
||||||
case White:
|
case White:
|
||||||
return whiteBackgroundColorAttr
|
return attrWhiteBackgroundColor
|
||||||
case BrightBlack:
|
case BrightBlack:
|
||||||
return brightBlackBackgroundColorAttr
|
return attrBrightBlackBackgroundColor
|
||||||
case BrightRed:
|
case BrightRed:
|
||||||
return brightRedBackgroundColorAttr
|
return attrBrightRedBackgroundColor
|
||||||
case BrightGreen:
|
case BrightGreen:
|
||||||
return brightGreenBackgroundColorAttr
|
return attrBrightGreenBackgroundColor
|
||||||
case BrightYellow:
|
case BrightYellow:
|
||||||
return brightYellowBackgroundColorAttr
|
return attrBrightYellowBackgroundColor
|
||||||
case BrightBlue:
|
case BrightBlue:
|
||||||
return brightBlueBackgroundColorAttr
|
return attrBrightBlueBackgroundColor
|
||||||
case BrightMagenta:
|
case BrightMagenta:
|
||||||
return brightMagentaBackgroundColorAttr
|
return attrBrightMagentaBackgroundColor
|
||||||
case BrightCyan:
|
case BrightCyan:
|
||||||
return brightCyanBackgroundColorAttr
|
return attrBrightCyanBackgroundColor
|
||||||
case BrightWhite:
|
case BrightWhite:
|
||||||
return brightWhiteBackgroundColorAttr
|
return attrBrightWhiteBackgroundColor
|
||||||
}
|
}
|
||||||
case ExtendedColor:
|
case ExtendedColor:
|
||||||
// 256-color ANSI foreground
|
// 256-color ANSI foreground
|
||||||
@ -472,7 +595,7 @@ func backgroundColorString(c Color) string {
|
|||||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||||
strconv.FormatUint(uint64(shift(b)), 10)
|
strconv.FormatUint(uint64(shift(b)), 10)
|
||||||
}
|
}
|
||||||
return defaultBackgroundColorAttr
|
return attrDefaultBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// underlineColorString returns the style SGR attribute for the given underline
|
// underlineColorString returns the style SGR attribute for the given underline
|
||||||
@ -498,7 +621,7 @@ func underlineColorString(c Color) string {
|
|||||||
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
strconv.FormatUint(uint64(shift(g)), 10) + ";" +
|
||||||
strconv.FormatUint(uint64(shift(b)), 10)
|
strconv.FormatUint(uint64(shift(b)), 10)
|
||||||
}
|
}
|
||||||
return defaultUnderlineColorAttr
|
return attrDefaultUnderlineColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadStyleColor decodes a color from a slice of parameters. It returns the
|
// ReadStyleColor decodes a color from a slice of parameters. It returns the
|
||||||
@ -526,7 +649,7 @@ func underlineColorString(c Color) string {
|
|||||||
// 2. Support ignoring and omitting the color space id (second parameter) with respect to RGB colors
|
// 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
|
// 3. Support ignoring and omitting the 6th parameter with respect to RGB and CMY colors
|
||||||
// 4. Support reading RGBA 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
|
if len(params) < 2 { // Need at least SGR type and color type
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -535,7 +658,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
|||||||
s := params[0]
|
s := params[0]
|
||||||
p := params[1]
|
p := params[1]
|
||||||
colorType := p.Param(0)
|
colorType := p.Param(0)
|
||||||
n = 2
|
n := 2
|
||||||
|
|
||||||
paramsfn := func() (p1, p2, p3, p4 int) {
|
paramsfn := func() (p1, p2, p3, p4 int) {
|
||||||
// Where should we start reading the color?
|
// Where should we start reading the color?
|
||||||
@ -594,7 +717,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
|||||||
B: uint8(b), //nolint:gosec
|
B: uint8(b), //nolint:gosec
|
||||||
A: 0xff,
|
A: 0xff,
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return n
|
||||||
|
|
||||||
case 3: // CMY direct color
|
case 3: // CMY direct color
|
||||||
if len(params) < 5 {
|
if len(params) < 5 {
|
||||||
@ -612,7 +735,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
|||||||
Y: uint8(y), //nolint:gosec
|
Y: uint8(y), //nolint:gosec
|
||||||
K: 0,
|
K: 0,
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return n
|
||||||
|
|
||||||
case 4: // CMYK direct color
|
case 4: // CMYK direct color
|
||||||
if len(params) < 6 {
|
if len(params) < 6 {
|
||||||
@ -630,7 +753,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
|||||||
Y: uint8(y), //nolint:gosec
|
Y: uint8(y), //nolint:gosec
|
||||||
K: uint8(k), //nolint:gosec
|
K: uint8(k), //nolint:gosec
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return n
|
||||||
|
|
||||||
case 5: // indexed color
|
case 5: // indexed color
|
||||||
if len(params) < 3 {
|
if len(params) < 3 {
|
||||||
@ -665,7 +788,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
|||||||
B: uint8(b), //nolint:gosec
|
B: uint8(b), //nolint:gosec
|
||||||
A: uint8(a), //nolint:gosec
|
A: uint8(a), //nolint:gosec
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return n
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0
|
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
|
package ansi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"strings"
|
||||||
|
|
||||||
"github.com/charmbracelet/x/ansi/parser"
|
"github.com/charmbracelet/x/ansi/parser"
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/clipperhouse/displaywidth"
|
||||||
"github.com/rivo/uniseg"
|
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cut the string, without adding any prefix or tail strings. This function is
|
// 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 ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var cluster []byte
|
var cluster string
|
||||||
var buf bytes.Buffer
|
var buf strings.Builder
|
||||||
curWidth := 0
|
curWidth := 0
|
||||||
ignoring := false
|
ignoring := false
|
||||||
pstate := parser.GroundState // initial state
|
pstate := parser.GroundState // initial state
|
||||||
b := []byte(s)
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
// Here we iterate over the bytes of the string and collect printable
|
// 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
|
// Once we reach the given length, we start ignoring characters and only
|
||||||
// collect ANSI escape codes until we reach the end of string.
|
// collect ANSI escape codes until we reach the end of string.
|
||||||
for i < len(b) {
|
for i < len(s) {
|
||||||
state, action := parser.Table.Transition(pstate, b[i])
|
state, action := parser.Table.Transition(pstate, s[i])
|
||||||
if state == parser.Utf8State {
|
if state == parser.Utf8State {
|
||||||
// This action happens when we transition to the Utf8State.
|
// This action happens when we transition to the Utf8State.
|
||||||
var width int
|
var width int
|
||||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(cluster))
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment the index by the length of the cluster
|
// increment the index by the length of the cluster
|
||||||
i += len(cluster)
|
i += len(cluster)
|
||||||
curWidth += width
|
curWidth += width
|
||||||
@ -118,7 +113,7 @@ func truncate(m Method, s string, length int, tail string) string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.Write(cluster)
|
buf.WriteString(cluster)
|
||||||
|
|
||||||
// Done collecting, now we're back in the ground state.
|
// Done collecting, now we're back in the ground state.
|
||||||
pstate = parser.GroundState
|
pstate = parser.GroundState
|
||||||
@ -152,7 +147,7 @@ func truncate(m Method, s string, length int, tail string) string {
|
|||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
buf.WriteByte(b[i])
|
buf.WriteByte(s[i])
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,27 +188,23 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
var cluster []byte
|
var cluster string
|
||||||
var buf bytes.Buffer
|
var buf strings.Builder
|
||||||
curWidth := 0
|
curWidth := 0
|
||||||
ignoring := true
|
ignoring := true
|
||||||
pstate := parser.GroundState
|
pstate := parser.GroundState
|
||||||
b := []byte(s)
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for i < len(b) {
|
for i < len(s) {
|
||||||
if !ignoring {
|
if !ignoring {
|
||||||
buf.Write(b[i:])
|
buf.WriteString(s[i:])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
state, action := parser.Table.Transition(pstate, b[i])
|
state, action := parser.Table.Transition(pstate, s[i])
|
||||||
if state == parser.Utf8State {
|
if state == parser.Utf8State {
|
||||||
var width int
|
var width int
|
||||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(cluster))
|
|
||||||
}
|
|
||||||
|
|
||||||
i += len(cluster)
|
i += len(cluster)
|
||||||
curWidth += width
|
curWidth += width
|
||||||
@ -224,7 +215,7 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if curWidth > n {
|
if curWidth > n {
|
||||||
buf.Write(cluster)
|
buf.WriteString(cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ignoring {
|
if ignoring {
|
||||||
@ -259,7 +250,7 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
|||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
buf.WriteByte(b[i])
|
buf.WriteByte(s[i])
|
||||||
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].
|
// You can use this with [Truncate], [TruncateLeft], and [Cut].
|
||||||
func ByteToGraphemeRange(str string, byteStart, byteStop int) (charStart, charStop int) {
|
func ByteToGraphemeRange(str string, byteStart, byteStop int) (charStart, charStop int) {
|
||||||
bytePos, charPos := 0, 0
|
bytePos, charPos := 0, 0
|
||||||
gr := uniseg.NewGraphemes(str)
|
gr := graphemes.FromString(str)
|
||||||
for byteStart > bytePos {
|
for byteStart > bytePos {
|
||||||
if !gr.Next() {
|
if !gr.Next() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bytePos += len(gr.Str())
|
bytePos += len(gr.Value())
|
||||||
charPos += max(1, gr.Width())
|
charPos += max(1, displaywidth.String(gr.Value()))
|
||||||
}
|
}
|
||||||
charStart = charPos
|
charStart = charPos
|
||||||
for byteStop > bytePos {
|
for byteStop > bytePos {
|
||||||
if !gr.Next() {
|
if !gr.Next() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bytePos += len(gr.Str())
|
bytePos += len(gr.Value())
|
||||||
charPos += max(1, gr.Width())
|
charPos += max(1, displaywidth.String(gr.Value()))
|
||||||
}
|
}
|
||||||
charStop = charPos
|
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"
|
"bytes"
|
||||||
|
|
||||||
"github.com/charmbracelet/x/ansi/parser"
|
"github.com/charmbracelet/x/ansi/parser"
|
||||||
"github.com/mattn/go-runewidth"
|
|
||||||
"github.com/rivo/uniseg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Strip removes ANSI escape codes from a string.
|
// Strip removes ANSI escape codes from a string.
|
||||||
@ -83,20 +81,16 @@ func stringWidth(m Method, s string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
pstate = parser.GroundState // initial state
|
pstate = parser.GroundState // initial state
|
||||||
cluster string
|
width int
|
||||||
width int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
state, action := parser.Table.Transition(pstate, s[i])
|
state, action := parser.Table.Transition(pstate, s[i])
|
||||||
if state == parser.Utf8State {
|
if state == parser.Utf8State {
|
||||||
var w int
|
cluster, w := FirstGraphemeCluster(s[i:], m)
|
||||||
cluster, _, w, _ = uniseg.FirstGraphemeClusterInString(s[i:], -1)
|
|
||||||
if m == WcWidth {
|
|
||||||
w = runewidth.StringWidth(cluster)
|
|
||||||
}
|
|
||||||
width += w
|
width += w
|
||||||
|
|
||||||
i += len(cluster) - 1
|
i += len(cluster) - 1
|
||||||
pstate = parser.GroundState
|
pstate = parser.GroundState
|
||||||
continue
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/charmbracelet/x/ansi/parser"
|
"github.com/charmbracelet/x/ansi/parser"
|
||||||
"github.com/mattn/go-runewidth"
|
|
||||||
"github.com/rivo/uniseg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// nbsp is a non-breaking space.
|
// nbsp is a non-breaking space.
|
||||||
@ -55,12 +54,9 @@ func hardwrap(m Method, s string, limit int, preserveSpace bool) string {
|
|||||||
i := 0
|
i := 0
|
||||||
for i < len(b) {
|
for i < len(b) {
|
||||||
state, action := parser.Table.Transition(pstate, b[i])
|
state, action := parser.Table.Transition(pstate, b[i])
|
||||||
if state == parser.Utf8State { //nolint:nestif
|
if state == parser.Utf8State {
|
||||||
var width int
|
var width int
|
||||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
cluster, width = FirstGraphemeCluster(b[i:], m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(cluster))
|
|
||||||
}
|
|
||||||
i += len(cluster)
|
i += len(cluster)
|
||||||
|
|
||||||
if curWidth+width > limit {
|
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])
|
state, action := parser.Table.Transition(pstate, b[i])
|
||||||
if state == parser.Utf8State { //nolint:nestif
|
if state == parser.Utf8State { //nolint:nestif
|
||||||
var width int
|
var width int
|
||||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
cluster, width = FirstGraphemeCluster(b[i:], m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(cluster))
|
|
||||||
}
|
|
||||||
i += len(cluster)
|
i += len(cluster)
|
||||||
|
|
||||||
r, _ := utf8.DecodeRune(cluster)
|
r, _ := utf8.DecodeRune(cluster)
|
||||||
@ -303,7 +296,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cluster []byte
|
cluster string
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
word bytes.Buffer
|
word bytes.Buffer
|
||||||
space 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
|
curWidth int // written width of the line
|
||||||
wordLen int // word buffer len without ANSI escape codes
|
wordLen int // word buffer len without ANSI escape codes
|
||||||
pstate = parser.GroundState // initial state
|
pstate = parser.GroundState // initial state
|
||||||
b = []byte(s)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
addSpace := func() {
|
addSpace := func() {
|
||||||
|
if spaceWidth == 0 && space.Len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
curWidth += spaceWidth
|
curWidth += spaceWidth
|
||||||
buf.Write(space.Bytes())
|
buf.Write(space.Bytes())
|
||||||
space.Reset()
|
space.Reset()
|
||||||
@ -341,30 +336,27 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(b) {
|
for i < len(s) {
|
||||||
state, action := parser.Table.Transition(pstate, b[i])
|
state, action := parser.Table.Transition(pstate, s[i])
|
||||||
if state == parser.Utf8State { //nolint:nestif
|
if state == parser.Utf8State { //nolint:nestif
|
||||||
var width int
|
var width int
|
||||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
cluster, width = FirstGraphemeCluster(s[i:], m)
|
||||||
if m == WcWidth {
|
|
||||||
width = runewidth.StringWidth(string(cluster))
|
|
||||||
}
|
|
||||||
i += len(cluster)
|
i += len(cluster)
|
||||||
|
|
||||||
r, _ := utf8.DecodeRune(cluster)
|
r, _ := utf8.DecodeRuneInString(cluster)
|
||||||
switch {
|
switch {
|
||||||
case r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp: // nbsp is a non-breaking space
|
case r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp: // nbsp is a non-breaking space
|
||||||
addWord()
|
addWord()
|
||||||
space.WriteRune(r)
|
space.WriteRune(r)
|
||||||
spaceWidth += width
|
spaceWidth += width
|
||||||
case bytes.ContainsAny(cluster, breakpoints):
|
case strings.ContainsAny(cluster, breakpoints):
|
||||||
addSpace()
|
addSpace()
|
||||||
if curWidth+wordLen+width > limit {
|
if curWidth+wordLen+width > limit {
|
||||||
word.Write(cluster)
|
word.WriteString(cluster)
|
||||||
wordLen += width
|
wordLen += width
|
||||||
} else {
|
} else {
|
||||||
addWord()
|
addWord()
|
||||||
buf.Write(cluster)
|
buf.WriteString(cluster)
|
||||||
curWidth += width
|
curWidth += width
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -373,12 +365,17 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
addWord()
|
addWord()
|
||||||
}
|
}
|
||||||
|
|
||||||
word.Write(cluster)
|
word.WriteString(cluster)
|
||||||
wordLen += width
|
wordLen += width
|
||||||
|
|
||||||
if curWidth+wordLen+spaceWidth > limit {
|
if curWidth+wordLen+spaceWidth > limit {
|
||||||
addNewline()
|
addNewline()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if wordLen == limit {
|
||||||
|
// Hardwrap the word if it's too long
|
||||||
|
addWord()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pstate = parser.GroundState
|
pstate = parser.GroundState
|
||||||
@ -387,7 +384,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case parser.PrintAction, parser.ExecuteAction:
|
case parser.PrintAction, parser.ExecuteAction:
|
||||||
switch r := rune(b[i]); {
|
switch r := rune(s[i]); {
|
||||||
case r == '\n':
|
case r == '\n':
|
||||||
if wordLen == 0 {
|
if wordLen == 0 {
|
||||||
if curWidth+spaceWidth > limit {
|
if curWidth+spaceWidth > limit {
|
||||||
@ -424,6 +421,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
if curWidth == limit {
|
if curWidth == limit {
|
||||||
addNewline()
|
addNewline()
|
||||||
}
|
}
|
||||||
|
|
||||||
word.WriteRune(r)
|
word.WriteRune(r)
|
||||||
wordLen++
|
wordLen++
|
||||||
|
|
||||||
@ -438,7 +436,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
word.WriteByte(b[i])
|
word.WriteByte(s[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// We manage the UTF8 state separately manually above.
|
// 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
|
package cellbuf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -24,7 +25,7 @@ func NewCell(r rune, comb ...rune) (c *Cell) {
|
|||||||
}
|
}
|
||||||
c.Comb = comb
|
c.Comb = comb
|
||||||
c.Width = runewidth.StringWidth(string(append([]rune{r}, 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
|
// 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)
|
c.Comb = append(c.Comb, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGraphemeCell returns a new cell. This is a convenience function that
|
// 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)
|
c.Comb = append(c.Comb, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Line represents a line in the terminal.
|
// Line represents a line in the terminal.
|
||||||
@ -104,7 +105,7 @@ func (l Line) String() (s string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
s = strings.TrimRight(s, " ")
|
s = strings.TrimRight(s, " ")
|
||||||
return
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// At returns the cell at the given x position.
|
// 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++ {
|
for j := 1; j < maxCellWidth && x-j >= 0; j++ {
|
||||||
wide := l.At(x - j)
|
wide := l.At(x - j)
|
||||||
if wide != nil && wide.Width > 1 && j < wide.Width {
|
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()
|
l[x-j+k] = wide.Clone().Blank()
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -206,7 +207,7 @@ func (b *Buffer) String() (s string) {
|
|||||||
s += "\r\n"
|
s += "\r\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Line returns a pointer to the line at the given y position.
|
// 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 y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||||
for x := rect.Min.X; x < rect.Max.X; x += cellWidth {
|
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) {
|
func (c *Cell) Clone() (n *Cell) {
|
||||||
n = new(Cell)
|
n = new(Cell)
|
||||||
*n = *c
|
*n = *c
|
||||||
return
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blank makes the cell a blank cell by setting the rune to a space, comb to
|
// 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.
|
// These are the available underline styles.
|
||||||
const (
|
const (
|
||||||
NoUnderline = ansi.NoUnderlineStyle
|
NoUnderline = ansi.UnderlineStyleNone
|
||||||
SingleUnderline = ansi.SingleUnderlineStyle
|
SingleUnderline = ansi.UnderlineStyleSingle
|
||||||
DoubleUnderline = ansi.DoubleUnderlineStyle
|
DoubleUnderline = ansi.UnderlineStyleDouble
|
||||||
CurlyUnderline = ansi.CurlyUnderlineStyle
|
CurlyUnderline = ansi.UnderlineStyleCurly
|
||||||
DottedUnderline = ansi.DottedUnderlineStyle
|
DottedUnderline = ansi.UnderlineStyleDotted
|
||||||
DashedUnderline = ansi.DashedUnderlineStyle
|
DashedUnderline = ansi.UnderlineStyleDashed
|
||||||
)
|
)
|
||||||
|
|
||||||
// Style represents the Style of a cell.
|
// Style represents the Style of a cell.
|
||||||
@ -189,7 +189,7 @@ func (s Style) Sequence() string {
|
|||||||
|
|
||||||
var b ansi.Style
|
var b ansi.Style
|
||||||
|
|
||||||
if s.Attrs != 0 {
|
if s.Attrs != 0 { //nolint:nestif
|
||||||
if s.Attrs&BoldAttr != 0 {
|
if s.Attrs&BoldAttr != 0 {
|
||||||
b = b.Bold()
|
b = b.Bold()
|
||||||
}
|
}
|
||||||
@ -197,36 +197,31 @@ func (s Style) Sequence() string {
|
|||||||
b = b.Faint()
|
b = b.Faint()
|
||||||
}
|
}
|
||||||
if s.Attrs&ItalicAttr != 0 {
|
if s.Attrs&ItalicAttr != 0 {
|
||||||
b = b.Italic()
|
b = b.Italic(true)
|
||||||
}
|
}
|
||||||
if s.Attrs&SlowBlinkAttr != 0 {
|
if s.Attrs&SlowBlinkAttr != 0 {
|
||||||
b = b.SlowBlink()
|
b = b.Blink(true)
|
||||||
}
|
}
|
||||||
if s.Attrs&RapidBlinkAttr != 0 {
|
if s.Attrs&RapidBlinkAttr != 0 {
|
||||||
b = b.RapidBlink()
|
b = b.RapidBlink(true)
|
||||||
}
|
}
|
||||||
if s.Attrs&ReverseAttr != 0 {
|
if s.Attrs&ReverseAttr != 0 {
|
||||||
b = b.Reverse()
|
b = b.Reverse(true)
|
||||||
}
|
}
|
||||||
if s.Attrs&ConcealAttr != 0 {
|
if s.Attrs&ConcealAttr != 0 {
|
||||||
b = b.Conceal()
|
b = b.Conceal(true)
|
||||||
}
|
}
|
||||||
if s.Attrs&StrikethroughAttr != 0 {
|
if s.Attrs&StrikethroughAttr != 0 {
|
||||||
b = b.Strikethrough()
|
b = b.Strikethrough(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.UlStyle != NoUnderline {
|
if s.UlStyle != NoUnderline {
|
||||||
switch s.UlStyle {
|
switch u := s.UlStyle; u {
|
||||||
case SingleUnderline:
|
case NoUnderline:
|
||||||
b = b.Underline()
|
b = b.Underline(false)
|
||||||
case DoubleUnderline:
|
default:
|
||||||
b = b.DoubleUnderline()
|
b = b.Underline(true)
|
||||||
case CurlyUnderline:
|
b = b.UnderlineStyle(u)
|
||||||
b = b.CurlyUnderline()
|
|
||||||
case DottedUnderline:
|
|
||||||
b = b.DottedUnderline()
|
|
||||||
case DashedUnderline:
|
|
||||||
b = b.DashedUnderline()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Fg != nil {
|
if s.Fg != nil {
|
||||||
@ -268,64 +263,48 @@ func (s Style) DiffSequence(o Style) string {
|
|||||||
isNormal bool
|
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 != o.Attrs&BoldAttr {
|
||||||
if s.Attrs&BoldAttr != 0 {
|
if s.Attrs&BoldAttr != 0 {
|
||||||
b = b.Bold()
|
b = b.Bold()
|
||||||
} else if !isNormal {
|
} else if !isNormal {
|
||||||
isNormal = true
|
isNormal = true
|
||||||
b = b.NormalIntensity()
|
b = b.Normal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Attrs&FaintAttr != o.Attrs&FaintAttr {
|
if s.Attrs&FaintAttr != o.Attrs&FaintAttr {
|
||||||
if s.Attrs&FaintAttr != 0 {
|
if s.Attrs&FaintAttr != 0 {
|
||||||
b = b.Faint()
|
b = b.Faint()
|
||||||
} else if !isNormal {
|
} else if !isNormal {
|
||||||
b = b.NormalIntensity()
|
b = b.Normal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Attrs&ItalicAttr != o.Attrs&ItalicAttr {
|
if s.Attrs&ItalicAttr != o.Attrs&ItalicAttr {
|
||||||
if s.Attrs&ItalicAttr != 0 {
|
b = b.Italic(s.Attrs&ItalicAttr != 0)
|
||||||
b = b.Italic()
|
|
||||||
} else {
|
|
||||||
b = b.NoItalic()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if s.Attrs&SlowBlinkAttr != o.Attrs&SlowBlinkAttr {
|
if s.Attrs&SlowBlinkAttr != o.Attrs&SlowBlinkAttr {
|
||||||
if s.Attrs&SlowBlinkAttr != 0 {
|
if s.Attrs&SlowBlinkAttr != 0 {
|
||||||
b = b.SlowBlink()
|
b = b.Blink(true)
|
||||||
} else if !noBlink {
|
} else if !noBlink {
|
||||||
noBlink = true
|
noBlink = true
|
||||||
b = b.NoBlink()
|
b = b.Blink(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Attrs&RapidBlinkAttr != o.Attrs&RapidBlinkAttr {
|
if s.Attrs&RapidBlinkAttr != o.Attrs&RapidBlinkAttr {
|
||||||
if s.Attrs&RapidBlinkAttr != 0 {
|
if s.Attrs&RapidBlinkAttr != 0 {
|
||||||
b = b.RapidBlink()
|
b = b.RapidBlink(true)
|
||||||
} else if !noBlink {
|
} else if !noBlink {
|
||||||
b = b.NoBlink()
|
b = b.Blink(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.Attrs&ReverseAttr != o.Attrs&ReverseAttr {
|
if s.Attrs&ReverseAttr != o.Attrs&ReverseAttr {
|
||||||
if s.Attrs&ReverseAttr != 0 {
|
b = b.Reverse(s.Attrs&ReverseAttr != 0)
|
||||||
b = b.Reverse()
|
|
||||||
} else {
|
|
||||||
b = b.NoReverse()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if s.Attrs&ConcealAttr != o.Attrs&ConcealAttr {
|
if s.Attrs&ConcealAttr != o.Attrs&ConcealAttr {
|
||||||
if s.Attrs&ConcealAttr != 0 {
|
b = b.Conceal(s.Attrs&ConcealAttr != 0)
|
||||||
b = b.Conceal()
|
|
||||||
} else {
|
|
||||||
b = b.NoConceal()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if s.Attrs&StrikethroughAttr != o.Attrs&StrikethroughAttr {
|
if s.Attrs&StrikethroughAttr != o.Attrs&StrikethroughAttr {
|
||||||
if s.Attrs&StrikethroughAttr != 0 {
|
b = b.Strikethrough(s.Attrs&StrikethroughAttr != 0)
|
||||||
b = b.Strikethrough()
|
|
||||||
} else {
|
|
||||||
b = b.NoStrikethrough()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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)
|
return image.Pt(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rectange represents a rectangle.
|
// Rectangle represents a rectangle.
|
||||||
type Rectangle = image.Rectangle
|
type Rectangle = image.Rectangle
|
||||||
|
|
||||||
// Rect is a shorthand for 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()
|
blank := s.clearBlank()
|
||||||
if n > 0 {
|
if n > 0 { //nolint:nestif
|
||||||
// Scroll up (forward)
|
// Scroll up (forward)
|
||||||
v = s.scrollUp(n, top, bot, 0, maxY, blank)
|
v = s.scrollUp(n, top, bot, 0, maxY, blank)
|
||||||
if !v {
|
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.move(0, bot-n+1)
|
||||||
s.clearToBottom(nil)
|
s.clearToBottom(nil)
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < n; i++ {
|
for i := range n {
|
||||||
s.move(0, bot-i)
|
s.move(0, bot-i)
|
||||||
s.clearToEnd(nil, false)
|
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.
|
// Clear newly shifted-in lines.
|
||||||
if v &&
|
if v &&
|
||||||
(nonDestScrollRegion || (memoryBelow && top == 0)) {
|
(nonDestScrollRegion || (memoryBelow && top == 0)) {
|
||||||
for i := 0; i < -n; i++ {
|
for i := range -n {
|
||||||
s.move(0, top+i)
|
s.move(0, top+i)
|
||||||
s.clearToEnd(nil, false)
|
s.clearToEnd(nil, false)
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !v {
|
if !v {
|
||||||
return
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
s.scrollBuffer(s.curbuf, n, top, bot, blank)
|
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.
|
// scrollUp scrolls the screen up by n lines.
|
||||||
func (s *Screen) scrollUp(n, top, bot, minY, maxY int, blank *Cell) bool {
|
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.move(0, bot)
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
s.buf.WriteByte('\n')
|
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.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.DeleteLine(1))
|
s.buf.WriteString(ansi.DeleteLine(1))
|
||||||
} else if top == minY && bot == maxY {
|
} else if top == minY && bot == maxY {
|
||||||
if s.xtermLike {
|
supportsSU := s.caps.Contains(capSU)
|
||||||
|
if supportsSU {
|
||||||
s.move(0, bot)
|
s.move(0, bot)
|
||||||
} else {
|
} else {
|
||||||
s.move(0, top)
|
s.move(0, top)
|
||||||
}
|
}
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
if s.xtermLike {
|
if supportsSU {
|
||||||
s.buf.WriteString(ansi.ScrollUp(n))
|
s.buf.WriteString(ansi.ScrollUp(n))
|
||||||
} else {
|
} else {
|
||||||
s.buf.WriteString(strings.Repeat("\n", n))
|
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.
|
// scrollDown scrolls the screen down by n lines.
|
||||||
func (s *Screen) scrollDown(n, top, bot, minY, maxY int, blank *Cell) bool {
|
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.move(0, top)
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.ReverseIndex)
|
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 {
|
} else if top == minY && bot == maxY {
|
||||||
s.move(0, top)
|
s.move(0, top)
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
if s.xtermLike {
|
if s.caps.Contains(capSD) {
|
||||||
s.buf.WriteString(ansi.ScrollDown(n))
|
s.buf.WriteString(ansi.ScrollDown(n))
|
||||||
} else {
|
} else {
|
||||||
s.buf.WriteString(strings.Repeat(ansi.ReverseIndex, n))
|
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)
|
h += (h << 5) + uint64(r)
|
||||||
}
|
}
|
||||||
return
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashmap represents a single [Line] hash.
|
// hashmap represents a single [Line] hash.
|
||||||
@ -33,7 +33,7 @@ func (s *Screen) updateHashmap() {
|
|||||||
height := s.newbuf.Height()
|
height := s.newbuf.Height()
|
||||||
if len(s.oldhash) >= height && len(s.newhash) >= height {
|
if len(s.oldhash) >= height && len(s.newhash) >= height {
|
||||||
// rehash changed lines
|
// rehash changed lines
|
||||||
for i := 0; i < height; i++ {
|
for i := range height {
|
||||||
_, ok := s.touch[i]
|
_, ok := s.touch[i]
|
||||||
if ok {
|
if ok {
|
||||||
s.oldhash[i] = hash(s.curbuf.Line(i))
|
s.oldhash[i] = hash(s.curbuf.Line(i))
|
||||||
@ -48,14 +48,14 @@ func (s *Screen) updateHashmap() {
|
|||||||
if len(s.newhash) != height {
|
if len(s.newhash) != height {
|
||||||
s.newhash = make([]uint64, 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.oldhash[i] = hash(s.curbuf.Line(i))
|
||||||
s.newhash[i] = hash(s.newbuf.Line(i))
|
s.newhash[i] = hash(s.newbuf.Line(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.hashtab = make([]hashmap, height*2)
|
s.hashtab = make([]hashmap, height*2)
|
||||||
for i := 0; i < height; i++ {
|
for i := range height {
|
||||||
hashval := s.oldhash[i]
|
hashval := s.oldhash[i]
|
||||||
|
|
||||||
// Find matching hash or empty slot
|
// Find matching hash or empty slot
|
||||||
@ -71,7 +71,7 @@ func (s *Screen) updateHashmap() {
|
|||||||
s.hashtab[idx].oldcount++
|
s.hashtab[idx].oldcount++
|
||||||
s.hashtab[idx].oldindex = i
|
s.hashtab[idx].oldindex = i
|
||||||
}
|
}
|
||||||
for i := 0; i < height; i++ {
|
for i := range height {
|
||||||
hashval := s.newhash[i]
|
hashval := s.newhash[i]
|
||||||
|
|
||||||
// Find matching hash or empty slot
|
// Find matching hash or empty slot
|
||||||
@ -130,7 +130,7 @@ func (s *Screen) updateHashmap() {
|
|||||||
s.growHunks()
|
s.growHunks()
|
||||||
}
|
}
|
||||||
|
|
||||||
// scrollOldhash
|
// scrollOldhash.
|
||||||
func (s *Screen) scrollOldhash(n, top, bot int) {
|
func (s *Screen) scrollOldhash(n, top, bot int) {
|
||||||
if len(s.oldhash) == 0 {
|
if len(s.oldhash) == 0 {
|
||||||
return
|
return
|
||||||
@ -287,7 +287,7 @@ func (s *Screen) updateCost(from, to Line) (cost int) {
|
|||||||
cost++
|
cost++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return cost
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screen) updateCostBlank(to Line) (cost int) {
|
func (s *Screen) updateCostBlank(to Line) (cost int) {
|
||||||
@ -297,5 +297,5 @@ func (s *Screen) updateCostBlank(to Line) (cost int) {
|
|||||||
cost++
|
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"
|
"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 {
|
func ConvertLink(h Link, p colorprofile.Profile) Link {
|
||||||
if p == colorprofile.NoTTY {
|
if p == colorprofile.NoTTY {
|
||||||
return Link{}
|
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
|
var seq strings.Builder
|
||||||
|
|
||||||
width, height := s.newbuf.Width(), s.newbuf.Height()
|
width, height := s.newbuf.Width(), s.newbuf.Height()
|
||||||
if ty != fy {
|
if ty != fy { //nolint:nestif
|
||||||
var yseq string
|
var yseq string
|
||||||
if s.xtermLike && !s.opts.RelativeCursor {
|
if s.caps.Contains(capVPA) && !s.opts.RelativeCursor {
|
||||||
yseq = ansi.VerticalPositionAbsolute(ty + 1)
|
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
|
shouldScroll := !s.opts.AltScreen && fy+n >= s.scrollHeight
|
||||||
if lf := strings.Repeat("\n", n); shouldScroll || (fy+n < height && len(lf) < len(yseq)) {
|
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.
|
// TODO: Ensure we're not unintentionally scrolling the screen down.
|
||||||
yseq = lf
|
yseq = lf
|
||||||
s.scrollHeight = max(s.scrollHeight, fy+n)
|
s.scrollHeight = max(s.scrollHeight, fy+n)
|
||||||
|
if s.opts.MapNL {
|
||||||
|
fx = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if ty < fy {
|
} else if ty < fy {
|
||||||
n := fy - ty
|
n := fy - ty
|
||||||
@ -64,6 +68,7 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
|||||||
yseq = cuu
|
yseq = cuu
|
||||||
}
|
}
|
||||||
if n == 1 && fy-1 > 0 {
|
if n == 1 && fy-1 > 0 {
|
||||||
|
//nolint:godox
|
||||||
// TODO: Ensure we're not unintentionally scrolling the screen up.
|
// TODO: Ensure we're not unintentionally scrolling the screen up.
|
||||||
yseq = ansi.ReverseIndex
|
yseq = ansi.ReverseIndex
|
||||||
}
|
}
|
||||||
@ -72,9 +77,9 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
|||||||
seq.WriteString(yseq)
|
seq.WriteString(yseq)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tx != fx {
|
if tx != fx { //nolint:nestif
|
||||||
var xseq string
|
var xseq string
|
||||||
if s.xtermLike && !s.opts.RelativeCursor {
|
if s.caps.Contains(capHPA) && !s.opts.RelativeCursor {
|
||||||
xseq = ansi.HorizontalPositionAbsolute(tx + 1)
|
xseq = ansi.HorizontalPositionAbsolute(tx + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +98,8 @@ func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBa
|
|||||||
if tabs > 0 {
|
if tabs > 0 {
|
||||||
cht := ansi.CursorHorizontalForwardTab(tabs)
|
cht := ansi.CursorHorizontalForwardTab(tabs)
|
||||||
tab := strings.Repeat("\t", 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
|
// TODO: The linux console and some terminals such as
|
||||||
// Alacritty don't support [ansi.CHT]. Enable this when
|
// Alacritty don't support [ansi.CHT]. Enable this when
|
||||||
// we have a way to detect this, or after 5 years 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 {
|
} else if tx < fx {
|
||||||
n := fx - tx
|
n := fx - tx
|
||||||
if useTabs && s.xtermLike {
|
if useTabs && s.caps.Contains(capCBT) {
|
||||||
// VT100 does not support backward tabs [ansi.CBT].
|
// VT100 does not support backward tabs [ansi.CBT].
|
||||||
|
|
||||||
col := fx
|
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.
|
// Method #0: Use [ansi.CUP] if the distance is long.
|
||||||
seq = ansi.CursorPosition(x+1, y+1)
|
seq = ansi.CursorPosition(x+1, y+1)
|
||||||
if fx == -1 || fy == -1 || notLocal(s.newbuf.Width(), fx, fy, x, y) {
|
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.
|
// 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 {
|
if !s.opts.AltScreen && s.cur.X == -1 && s.cur.Y == -1 {
|
||||||
// First cursor movement in inline mode, move the cursor to the first
|
// First cursor movement in inline mode, move the cursor to the first
|
||||||
// column before moving to the target position.
|
// 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.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
|
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
|
// Reset wrap around (phantom cursor) state
|
||||||
if s.atPhantom {
|
if s.atPhantom {
|
||||||
s.cur.X = 0
|
s.cur.X = 0
|
||||||
s.buf.WriteByte('\r') //nolint:errcheck
|
s.buf.WriteByte('\r')
|
||||||
s.atPhantom = false // reset phantom cell state
|
s.atPhantom = false // reset phantom cell state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:godox
|
||||||
// TODO: Investigate if we need to handle this case and/or if we need the
|
// TODO: Investigate if we need to handle this case and/or if we need the
|
||||||
// following code.
|
// following code.
|
||||||
//
|
//
|
||||||
@ -291,7 +298,7 @@ func (s *Screen) move(x, y int) {
|
|||||||
//
|
//
|
||||||
// if l > 0 {
|
// if l > 0 {
|
||||||
// s.cur.X = 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
|
HardTabs bool
|
||||||
// Backspace is whether to use backspace characters to move the cursor.
|
// Backspace is whether to use backspace characters to move the cursor.
|
||||||
Backspace bool
|
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.
|
// lineData represents the metadata for a line.
|
||||||
@ -365,13 +376,13 @@ type Screen struct {
|
|||||||
opts ScreenOptions
|
opts ScreenOptions
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
method ansi.Method
|
method ansi.Method
|
||||||
scrollHeight int // keeps track of how many lines we've scrolled down (inline mode)
|
scrollHeight int // keeps track of how many lines we've scrolled down (inline mode)
|
||||||
altScreenMode bool // whether alternate screen mode is enabled
|
altScreenMode bool // whether alternate screen mode is enabled
|
||||||
cursorHidden bool // whether text cursor mode is enabled
|
cursorHidden bool // whether text cursor mode is enabled
|
||||||
clear bool // whether to force clear the screen
|
clear bool // whether to force clear the screen
|
||||||
xtermLike bool // whether to use xterm-like optimizations, otherwise, it uses vt100 only
|
caps capabilities // terminal control sequence capabilities
|
||||||
queuedText bool // whether we have queued non-zero width text queued up
|
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
|
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.
|
// 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
|
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.
|
// terminal supports ECMA-48 and ANSI X3.64 escape sequences.
|
||||||
// TODO: Should this be a lookup table into each $TERM terminfo database? Like
|
// xtermCaps returns a list of control sequence capabilities for the given
|
||||||
// we could keep a map of ANSI escape sequence to terminfo capability name and
|
// terminal type. This only supports a subset of sequences that can
|
||||||
// check if the database supports the escape sequence. Instead of keeping a
|
// be different among terminals.
|
||||||
// list of terminal names here.
|
// NOTE: A hybrid approach would be to support Terminfo databases for a full
|
||||||
func isXtermLike(termtype string) (v bool) {
|
// set of capabilities.
|
||||||
|
func xtermCaps(termtype string) (v capabilities) {
|
||||||
parts := strings.Split(termtype, "-")
|
parts := strings.Split(termtype, "-")
|
||||||
if len(parts) == 0 {
|
if len(parts) == 0 {
|
||||||
return
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case
|
case
|
||||||
"alacritty",
|
|
||||||
"contour",
|
"contour",
|
||||||
"foot",
|
"foot",
|
||||||
"ghostty",
|
"ghostty",
|
||||||
"kitty",
|
"kitty",
|
||||||
"linux",
|
|
||||||
"rio",
|
"rio",
|
||||||
"screen",
|
|
||||||
"st",
|
"st",
|
||||||
"tmux",
|
"tmux",
|
||||||
"wezterm",
|
"wezterm",
|
||||||
"xterm":
|
"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.
|
// 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.buf = new(bytes.Buffer)
|
||||||
s.xtermLike = isXtermLike(s.opts.Term)
|
s.caps = xtermCaps(s.opts.Term)
|
||||||
s.curbuf = NewBuffer(width, height)
|
s.curbuf = NewBuffer(width, height)
|
||||||
s.newbuf = NewBuffer(width, height)
|
s.newbuf = NewBuffer(width, height)
|
||||||
s.cur = Cursor{Position: Pos(-1, -1)} // start at -1 to force a move
|
s.cur = Cursor{Position: Pos(-1, -1)} // start at -1 to force a move
|
||||||
s.saved = s.cur
|
s.saved = s.cur
|
||||||
s.reset()
|
s.reset()
|
||||||
|
|
||||||
return
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Width returns the width of the screen.
|
// 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.
|
// wrapCursor wraps the cursor to the next line.
|
||||||
//
|
//
|
||||||
//nolint:unused
|
|
||||||
func (s *Screen) wrapCursor() {
|
func (s *Screen) wrapCursor() {
|
||||||
const autoRightMargin = true
|
const autoRightMargin = true
|
||||||
if autoRightMargin {
|
if autoRightMargin {
|
||||||
@ -628,9 +680,9 @@ func (s *Screen) putAttrCell(cell *Cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.updatePen(cell)
|
s.updatePen(cell)
|
||||||
s.buf.WriteRune(cell.Rune) //nolint:errcheck
|
s.buf.WriteRune(cell.Rune)
|
||||||
for _, c := range cell.Comb {
|
for _, c := range cell.Comb {
|
||||||
s.buf.WriteRune(c) //nolint:errcheck
|
s.buf.WriteRune(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cur.X += cell.Width
|
s.cur.X += cell.Width
|
||||||
@ -649,12 +701,12 @@ func (s *Screen) putCellLR(cell *Cell) {
|
|||||||
// Optimize for the lower right corner cell.
|
// Optimize for the lower right corner cell.
|
||||||
curX := s.cur.X
|
curX := s.cur.X
|
||||||
if cell == nil || !cell.Empty() {
|
if cell == nil || !cell.Empty() {
|
||||||
s.buf.WriteString(ansi.ResetAutoWrapMode) //nolint:errcheck
|
s.buf.WriteString(ansi.ResetModeAutoWrap)
|
||||||
s.putAttrCell(cell)
|
s.putAttrCell(cell)
|
||||||
// Writing to lower-right corner cell should not wrap.
|
// Writing to lower-right corner cell should not wrap.
|
||||||
s.atPhantom = false
|
s.atPhantom = false
|
||||||
s.cur.X = curX
|
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) {
|
if cell.Style.Empty() && len(seq) > len(ansi.ResetStyle) {
|
||||||
seq = ansi.ResetStyle
|
seq = ansi.ResetStyle
|
||||||
}
|
}
|
||||||
s.buf.WriteString(seq) //nolint:errcheck
|
s.buf.WriteString(seq)
|
||||||
s.cur.Style = cell.Style
|
s.cur.Style = cell.Style
|
||||||
}
|
}
|
||||||
if !cell.Link.Equal(&s.cur.Link) {
|
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
|
s.cur.Link = cell.Link
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -712,9 +764,9 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
|||||||
ech := ansi.EraseCharacter(count)
|
ech := ansi.EraseCharacter(count)
|
||||||
cup := ansi.CursorPosition(s.cur.X+count, s.cur.Y)
|
cup := ansi.CursorPosition(s.cur.X+count, s.cur.Y)
|
||||||
rep := ansi.RepeatPreviousCharacter(count)
|
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.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 this is the last cell, we don't need to move the cursor.
|
||||||
if count < n {
|
if count < n {
|
||||||
@ -722,7 +774,7 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
|||||||
} else {
|
} else {
|
||||||
return true // cursor in the middle
|
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)) {
|
(cell0 == nil || (len(cell0.Comb) == 0 && cell0.Rune < 256)) {
|
||||||
// We only support ASCII characters. Most terminals will handle
|
// We only support ASCII characters. Most terminals will handle
|
||||||
// non-ASCII characters correctly, but some might not, ahem xterm.
|
// 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)
|
s.putCell(cell0)
|
||||||
repCount-- // cell0 is a single width cell ASCII character
|
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
|
s.cur.X += repCount
|
||||||
if wrapPossible {
|
if wrapPossible {
|
||||||
s.putCell(cell0)
|
s.putCell(cell0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < count; i++ {
|
for i := range count {
|
||||||
s.putCell(line.At(i))
|
s.putCell(line.At(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,7 +807,7 @@ func (s *Screen) emitRange(line Line, n int) (eoi bool) {
|
|||||||
n -= count
|
n -= count
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return eoi
|
||||||
}
|
}
|
||||||
|
|
||||||
// putRange puts a range of cells from the old line to the new line.
|
// 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)),
|
inline := min(len(ansi.CursorPosition(start+1, y+1)),
|
||||||
min(len(ansi.HorizontalPositionAbsolute(start+1)),
|
min(len(ansi.HorizontalPositionAbsolute(start+1)),
|
||||||
len(ansi.CursorForward(start+1))))
|
len(ansi.CursorForward(start+1))))
|
||||||
if (end - start + 1) > inline {
|
if (end - start + 1) > inline { //nolint:nestif
|
||||||
var j, same int
|
var j, same int
|
||||||
for j, same = start, 0; j <= end; j++ {
|
for j, same = start, 0; j <= end; j++ {
|
||||||
oldCell, newCell := oldLine.At(j), newLine.At(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)
|
s.updatePen(blank)
|
||||||
count := s.newbuf.Width() - s.cur.X
|
count := s.newbuf.Width() - s.cur.X
|
||||||
if s.el0Cost() <= count {
|
if s.el0Cost() <= count {
|
||||||
s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck
|
s.buf.WriteString(ansi.EraseLineRight)
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < count; i++ {
|
for range count {
|
||||||
s.putCell(blank)
|
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
|
// insertCells inserts the count cells pointed by the given line at the current
|
||||||
// cursor position.
|
// cursor position.
|
||||||
func (s *Screen) insertCells(line Line, count int) {
|
func (s *Screen) insertCells(line Line, count int) {
|
||||||
if s.xtermLike {
|
supportsICH := s.caps.Contains(capICH)
|
||||||
|
if supportsICH {
|
||||||
// Use [ansi.ICH] as an optimization.
|
// Use [ansi.ICH] as an optimization.
|
||||||
s.buf.WriteString(ansi.InsertCharacter(count)) //nolint:errcheck
|
s.buf.WriteString(ansi.InsertCharacter(count))
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, use [ansi.IRM] mode.
|
// Otherwise, use [ansi.IRM] mode.
|
||||||
s.buf.WriteString(ansi.SetInsertReplaceMode) //nolint:errcheck
|
s.buf.WriteString(ansi.SetModeInsertReplace)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; count > 0; i++ {
|
for i := 0; count > 0; i++ {
|
||||||
@ -852,8 +905,8 @@ func (s *Screen) insertCells(line Line, count int) {
|
|||||||
count--
|
count--
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.xtermLike {
|
if !supportsICH {
|
||||||
s.buf.WriteString(ansi.ResetInsertReplaceMode) //nolint:errcheck
|
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
|
// [ansi.EL] 0 i.e. [ansi.EraseLineRight] to clear
|
||||||
// trailing spaces.
|
// trailing spaces.
|
||||||
func (s *Screen) el0Cost() int {
|
func (s *Screen) el0Cost() int {
|
||||||
if s.xtermLike {
|
if s.caps != noCaps {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return len(ansi.EraseLineRight)
|
return len(ansi.EraseLineRight)
|
||||||
@ -878,7 +931,7 @@ func (s *Screen) transformLine(y int) {
|
|||||||
|
|
||||||
// Find the first changed cell in the line
|
// Find the first changed cell in the line
|
||||||
var lineChanged bool
|
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)) {
|
if !cellEqual(newLine.At(i), oldLine.At(i)) {
|
||||||
lineChanged = true
|
lineChanged = true
|
||||||
break
|
break
|
||||||
@ -886,7 +939,7 @@ func (s *Screen) transformLine(y int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ceolStandoutGlitch = false
|
const ceolStandoutGlitch = false
|
||||||
if ceolStandoutGlitch && lineChanged {
|
if ceolStandoutGlitch && lineChanged { //nolint:nestif
|
||||||
s.move(0, y)
|
s.move(0, y)
|
||||||
s.clearToEnd(nil, false)
|
s.clearToEnd(nil, false)
|
||||||
s.putRange(oldLine, newLine, y, 0, s.newbuf.Width()-1)
|
s.putRange(oldLine, newLine, y, 0, s.newbuf.Width()-1)
|
||||||
@ -897,12 +950,12 @@ func (s *Screen) transformLine(y int) {
|
|||||||
// [ansi.EraseLineLeft].
|
// [ansi.EraseLineLeft].
|
||||||
if blank == nil || blank.Clear() {
|
if blank == nil || blank.Clear() {
|
||||||
var oFirstCell, nFirstCell int
|
var oFirstCell, nFirstCell int
|
||||||
for oFirstCell = 0; oFirstCell < s.curbuf.Width(); oFirstCell++ {
|
for oFirstCell = range s.curbuf.Width() {
|
||||||
if !cellEqual(oldLine.At(oFirstCell), blank) {
|
if !cellEqual(oldLine.At(oFirstCell), blank) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for nFirstCell = 0; nFirstCell < s.newbuf.Width(); nFirstCell++ {
|
for nFirstCell = range s.newbuf.Width() {
|
||||||
if !cellEqual(newLine.At(nFirstCell), blank) {
|
if !cellEqual(newLine.At(nFirstCell), blank) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -925,11 +978,11 @@ func (s *Screen) transformLine(y int) {
|
|||||||
if nFirstCell >= s.newbuf.Width() {
|
if nFirstCell >= s.newbuf.Width() {
|
||||||
s.move(0, y)
|
s.move(0, y)
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck
|
s.buf.WriteString(ansi.EraseLineRight)
|
||||||
} else {
|
} else {
|
||||||
s.move(nFirstCell-1, y)
|
s.move(nFirstCell-1, y)
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.EraseLineLeft) //nolint:errcheck
|
s.buf.WriteString(ansi.EraseLineLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
for firstCell < nFirstCell {
|
for firstCell < nFirstCell {
|
||||||
@ -1045,7 +1098,7 @@ func (s *Screen) transformLine(y int) {
|
|||||||
|
|
||||||
s.move(n+1, y)
|
s.move(n+1, y)
|
||||||
ichCost := 3 + nLastCell - oLastCell
|
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)
|
s.putRange(oldLine, newLine, y, n+1, m)
|
||||||
} else {
|
} else {
|
||||||
s.insertCells(newLine[n+1:], nLastCell-oLastCell)
|
s.insertCells(newLine[n+1:], nLastCell-oLastCell)
|
||||||
@ -1079,7 +1132,7 @@ func (s *Screen) transformLine(y int) {
|
|||||||
func (s *Screen) deleteCells(count int) {
|
func (s *Screen) deleteCells(count int) {
|
||||||
// [ansi.DCH] will shift in cells from the right margin so we need to
|
// [ansi.DCH] will shift in cells from the right margin so we need to
|
||||||
// ensure that they are the right style.
|
// 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
|
// 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.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.EraseScreenBelow) //nolint:errcheck
|
s.buf.WriteString(ansi.EraseScreenBelow)
|
||||||
// Clear the rest of the current line
|
// Clear the rest of the current line
|
||||||
s.curbuf.ClearRect(Rect(col, row, s.curbuf.Width()-col, 1))
|
s.curbuf.ClearRect(Rect(col, row, s.curbuf.Width()-col, 1))
|
||||||
// Clear everything below the current line
|
// Clear everything below the current line
|
||||||
@ -1104,7 +1157,7 @@ func (s *Screen) clearToBottom(blank *Cell) {
|
|||||||
// It returns the top line.
|
// It returns the top line.
|
||||||
func (s *Screen) clearBottom(total int) (top int) {
|
func (s *Screen) clearBottom(total int) (top int) {
|
||||||
if total <= 0 {
|
if total <= 0 {
|
||||||
return
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
top = total
|
top = total
|
||||||
@ -1112,7 +1165,7 @@ func (s *Screen) clearBottom(total int) (top int) {
|
|||||||
blank := s.clearBlank()
|
blank := s.clearBlank()
|
||||||
canClearWithBlank := blank == nil || blank.Clear()
|
canClearWithBlank := blank == nil || blank.Clear()
|
||||||
|
|
||||||
if canClearWithBlank {
|
if canClearWithBlank { //nolint:nestif
|
||||||
var row int
|
var row int
|
||||||
for row = total - 1; row >= 0; row-- {
|
for row = total - 1; row >= 0; row-- {
|
||||||
oldLine := s.curbuf.Line(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.
|
// clearScreen clears the screen and put cursor at home.
|
||||||
func (s *Screen) clearScreen(blank *Cell) {
|
func (s *Screen) clearScreen(blank *Cell) {
|
||||||
s.updatePen(blank)
|
s.updatePen(blank)
|
||||||
s.buf.WriteString(ansi.CursorHomePosition) //nolint:errcheck
|
s.buf.WriteString(ansi.CursorHomePosition)
|
||||||
s.buf.WriteString(ansi.EraseEntireScreen) //nolint:errcheck
|
s.buf.WriteString(ansi.EraseEntireScreen)
|
||||||
s.cur.X, s.cur.Y = 0, 0
|
s.cur.X, s.cur.Y = 0, 0
|
||||||
s.curbuf.Fill(blank)
|
s.curbuf.Fill(blank)
|
||||||
}
|
}
|
||||||
@ -1179,7 +1232,7 @@ func (s *Screen) clearUpdate() {
|
|||||||
s.clearBelow(blank, 0)
|
s.clearBelow(blank, 0)
|
||||||
}
|
}
|
||||||
nonEmpty = s.clearBottom(nonEmpty)
|
nonEmpty = s.clearBottom(nonEmpty)
|
||||||
for i := 0; i < nonEmpty; i++ {
|
for i := range nonEmpty {
|
||||||
s.transformLine(i)
|
s.transformLine(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1194,13 +1247,13 @@ func (s *Screen) Flush() (err error) {
|
|||||||
func (s *Screen) flush() (err error) {
|
func (s *Screen) flush() (err error) {
|
||||||
// Write the buffer
|
// Write the buffer
|
||||||
if s.buf.Len() > 0 {
|
if s.buf.Len() > 0 {
|
||||||
_, err = s.w.Write(s.buf.Bytes()) //nolint:errcheck
|
_, err = s.w.Write(s.buf.Bytes())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.buf.Reset()
|
s.buf.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders changes of the screen to the internal buffer. Call
|
// Render renders changes of the screen to the internal buffer. Call
|
||||||
@ -1221,6 +1274,7 @@ func (s *Screen) render() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:godox
|
||||||
// TODO: Investigate whether this is necessary. Theoretically, terminals
|
// TODO: Investigate whether this is necessary. Theoretically, terminals
|
||||||
// can add/remove tab stops and we should be able to handle that. We could
|
// 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
|
// 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?
|
// Do we need alt-screen mode?
|
||||||
if s.opts.AltScreen != s.altScreenMode {
|
if s.opts.AltScreen != s.altScreenMode {
|
||||||
if s.opts.AltScreen {
|
if s.opts.AltScreen {
|
||||||
s.buf.WriteString(ansi.SetAltScreenSaveCursorMode)
|
s.buf.WriteString(ansi.SetModeAltScreenSaveCursor)
|
||||||
} else {
|
} else {
|
||||||
s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode)
|
s.buf.WriteString(ansi.ResetModeAltScreenSaveCursor)
|
||||||
}
|
}
|
||||||
s.altScreenMode = s.opts.AltScreen
|
s.altScreenMode = s.opts.AltScreen
|
||||||
}
|
}
|
||||||
@ -1252,7 +1306,9 @@ func (s *Screen) render() {
|
|||||||
|
|
||||||
// Do we have queued strings to write above the screen?
|
// Do we have queued strings to write above the screen?
|
||||||
if len(s.queueAbove) > 0 {
|
if len(s.queueAbove) > 0 {
|
||||||
|
//nolint:godox
|
||||||
// TODO: Use scrolling region if available.
|
// TODO: Use scrolling region if available.
|
||||||
|
//nolint:godox
|
||||||
// TODO: Use [Screen.Write] [io.Writer] interface.
|
// TODO: Use [Screen.Write] [io.Writer] interface.
|
||||||
|
|
||||||
// We need to scroll the screen up by the number of lines in the queue.
|
// 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)
|
s.clearBelow(nil, s.newbuf.Height()-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.clear {
|
if s.clear { //nolint:nestif
|
||||||
s.clearUpdate()
|
s.clearUpdate()
|
||||||
s.clear = false
|
s.clear = false
|
||||||
} else if len(s.touch) > 0 {
|
} else if len(s.touch) > 0 {
|
||||||
if s.opts.AltScreen {
|
if s.opts.AltScreen {
|
||||||
// Optimize scrolling for the alternate screen buffer.
|
// Optimize scrolling for the alternate screen buffer.
|
||||||
|
//nolint:godox
|
||||||
// TODO: Should we optimize for inline mode as well? If so, we need
|
// TODO: Should we optimize for inline mode as well? If so, we need
|
||||||
// to know the actual cursor position to use [ansi.DECSTBM].
|
// to know the actual cursor position to use [ansi.DECSTBM].
|
||||||
s.scrollOptimize()
|
s.scrollOptimize()
|
||||||
@ -1311,7 +1368,7 @@ func (s *Screen) render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nonEmpty = s.clearBottom(nonEmpty)
|
nonEmpty = s.clearBottom(nonEmpty)
|
||||||
for i = 0; i < nonEmpty; i++ {
|
for i = range nonEmpty {
|
||||||
_, ok := s.touch[i]
|
_, ok := s.touch[i]
|
||||||
if ok {
|
if ok {
|
||||||
s.transformLine(i)
|
s.transformLine(i)
|
||||||
@ -1359,7 +1416,7 @@ func (s *Screen) Close() (err error) {
|
|||||||
s.move(0, s.newbuf.Height()-1)
|
s.move(0, s.newbuf.Height()-1)
|
||||||
|
|
||||||
if s.altScreenMode {
|
if s.altScreenMode {
|
||||||
s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode)
|
s.buf.WriteString(ansi.ResetModeAltScreenSaveCursor)
|
||||||
s.altScreenMode = false
|
s.altScreenMode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,11 +1428,11 @@ func (s *Screen) Close() (err error) {
|
|||||||
// Write the buffer
|
// Write the buffer
|
||||||
err = s.flush()
|
err = s.flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.reset()
|
s.reset()
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset resets the screen to its initial state.
|
// reset resets the screen to its initial state.
|
||||||
@ -1420,9 +1477,9 @@ func (s *Screen) Resize(width, height int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if height > oldh {
|
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 {
|
} 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()
|
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"
|
"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 {
|
func ConvertStyle(s Style, p colorprofile.Profile) Style {
|
||||||
switch p {
|
switch p { //nolint:exhaustive
|
||||||
case colorprofile.TrueColor:
|
case colorprofile.TrueColor:
|
||||||
return s
|
return s
|
||||||
case colorprofile.Ascii:
|
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
|
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 {
|
func clamp(v, low, high int) int {
|
||||||
if high < low {
|
if high < low {
|
||||||
low, high = 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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"slices"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
@ -20,6 +21,16 @@ const nbsp = '\u00a0'
|
|||||||
//
|
//
|
||||||
// Note: breakpoints must be a string of 1-cell wide rune characters.
|
// Note: breakpoints must be a string of 1-cell wide rune characters.
|
||||||
func Wrap(s string, limit int, breakpoints string) string {
|
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 {
|
if len(s) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -90,7 +101,7 @@ func Wrap(s string, limit int, breakpoints string) string {
|
|||||||
seq, width, n, newState := ansi.DecodeSequence(s, state, p)
|
seq, width, n, newState := ansi.DecodeSequence(s, state, p)
|
||||||
switch width {
|
switch width {
|
||||||
case 0:
|
case 0:
|
||||||
if ansi.Equal(seq, "\t") {
|
if ansi.Equal(seq, "\t") { //nolint:nestif
|
||||||
addWord()
|
addWord()
|
||||||
space.WriteString(seq)
|
space.WriteString(seq)
|
||||||
break
|
break
|
||||||
@ -176,10 +187,5 @@ func Wrap(s string, limit int, breakpoints string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runeContainsAny[T string | []rune](r rune, s T) bool {
|
func runeContainsAny[T string | []rune](r rune, s T) bool {
|
||||||
for _, c := range []rune(s) {
|
return slices.Contains([]rune(s), r)
|
||||||
if c == r {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
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) {
|
func FillRect(s CellBuffer, c *Cell, rect Rectangle) {
|
||||||
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||||
for x := rect.Min.X; x < rect.Max.X; x++ {
|
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 {
|
func Render(d CellBuffer) string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
height := d.Bounds().Dy()
|
height := d.Bounds().Dy()
|
||||||
for y := 0; y < height; y++ {
|
for y := range height {
|
||||||
_, line := RenderLine(d, y)
|
_, line := RenderLine(d, y)
|
||||||
buf.WriteString(line)
|
buf.WriteString(line)
|
||||||
if y < height-1 {
|
if y < height-1 {
|
||||||
@ -98,32 +98,32 @@ func RenderLine(d CellBuffer, n int) (w int, line string) {
|
|||||||
pendingLine = ""
|
pendingLine = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
for x := 0; x < d.Bounds().Dx(); x++ {
|
for x := range d.Bounds().Dx() {
|
||||||
if cell := d.Cell(x, n); cell != nil && cell.Width > 0 {
|
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.
|
// Convert the cell's style and link to the given color profile.
|
||||||
cellStyle := cell.Style
|
cellStyle := cell.Style
|
||||||
cellLink := cell.Link
|
cellLink := cell.Link
|
||||||
if cellStyle.Empty() && !pen.Empty() {
|
if cellStyle.Empty() && !pen.Empty() {
|
||||||
writePending()
|
writePending()
|
||||||
buf.WriteString(ansi.ResetStyle) //nolint:errcheck
|
buf.WriteString(ansi.ResetStyle)
|
||||||
pen.Reset()
|
pen.Reset()
|
||||||
}
|
}
|
||||||
if !cellStyle.Equal(&pen) {
|
if !cellStyle.Equal(&pen) {
|
||||||
writePending()
|
writePending()
|
||||||
seq := cellStyle.DiffSequence(pen)
|
seq := cellStyle.DiffSequence(pen)
|
||||||
buf.WriteString(seq) // nolint:errcheck
|
buf.WriteString(seq)
|
||||||
pen = cellStyle
|
pen = cellStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the URL escape sequence
|
// Write the URL escape sequence
|
||||||
if cellLink != link && link.URL != "" {
|
if cellLink != link && link.URL != "" {
|
||||||
writePending()
|
writePending()
|
||||||
buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck
|
buf.WriteString(ansi.ResetHyperlink())
|
||||||
link.Reset()
|
link.Reset()
|
||||||
}
|
}
|
||||||
if cellLink != link {
|
if cellLink != link {
|
||||||
writePending()
|
writePending()
|
||||||
buf.WriteString(ansi.SetHyperlink(cellLink.URL, cellLink.Params)) //nolint:errcheck
|
buf.WriteString(ansi.SetHyperlink(cellLink.URL, cellLink.Params))
|
||||||
link = cellLink
|
link = cellLink
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +140,10 @@ func RenderLine(d CellBuffer, n int) (w int, line string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if link.URL != "" {
|
if link.URL != "" {
|
||||||
buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck
|
buf.WriteString(ansi.ResetHyperlink())
|
||||||
}
|
}
|
||||||
if !pen.Empty() {
|
if !pen.Empty() {
|
||||||
buf.WriteString(ansi.ResetStyle) //nolint:errcheck
|
buf.WriteString(ansi.ResetStyle)
|
||||||
}
|
}
|
||||||
return w, strings.TrimRight(buf.String(), " ") // Trim trailing spaces
|
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.
|
// 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
|
// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape
|
||||||
// sequences.
|
// sequences.
|
||||||
func (s *ScreenWriter) Print(str string, v ...interface{}) {
|
func (s *ScreenWriter) Print(str string, v ...any) {
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
str = fmt.Sprintf(str, v...)
|
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.
|
// the width of the screen if it exceeds the width of the screen.
|
||||||
// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape
|
// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape
|
||||||
// sequences.
|
// 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 {
|
if len(v) > 0 {
|
||||||
str = fmt.Sprintf(str, v...)
|
str = fmt.Sprintf(str, v...)
|
||||||
}
|
}
|
||||||
@ -299,7 +299,7 @@ func printString[T []byte | string](
|
|||||||
// Print the cell to the screen
|
// Print the cell to the screen
|
||||||
cell.Style = style
|
cell.Style = style
|
||||||
cell.Link = link
|
cell.Link = link
|
||||||
s.SetCell(x, y, &cell) //nolint:errcheck
|
s.SetCell(x, y, &cell)
|
||||||
x += width
|
x += width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,6 +309,7 @@ func printString[T []byte | string](
|
|||||||
cell.Reset()
|
cell.Reset()
|
||||||
default:
|
default:
|
||||||
// Valid sequences always have a non-zero Cmd.
|
// Valid sequences always have a non-zero Cmd.
|
||||||
|
//nolint:godox
|
||||||
// TODO: Handle cursor movement and other sequences
|
// TODO: Handle cursor movement and other sequences
|
||||||
switch {
|
switch {
|
||||||
case ansi.HasCsiPrefix(seq) && p.Command() == 'm':
|
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.
|
// Make sure to set the last cell if it's not empty.
|
||||||
if !cell.Empty() {
|
if !cell.Empty() {
|
||||||
s.SetCell(x, y, &cell) //nolint:errcheck
|
s.SetCell(x, y, &cell)
|
||||||
cell.Reset()
|
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
|
package term
|
||||||
|
|
||||||
// State contains platform-specific state of a terminal.
|
// 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) {
|
func makeRaw(fd uintptr) (*State, error) {
|
||||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
oldState := State{state{Termios: *termios}}
|
oldState := State{state{Termios: *termios}}
|
||||||
@ -34,7 +34,7 @@ func makeRaw(fd uintptr) (*State, error) {
|
|||||||
termios.Cc[unix.VMIN] = 1
|
termios.Cc[unix.VMIN] = 1
|
||||||
termios.Cc[unix.VTIME] = 0
|
termios.Cc[unix.VTIME] = 0
|
||||||
if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios); err != nil {
|
if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios); err != nil {
|
||||||
return nil, err
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
return &oldState, nil
|
return &oldState, nil
|
||||||
@ -45,26 +45,26 @@ func setState(fd uintptr, state *State) error {
|
|||||||
if state != nil {
|
if state != nil {
|
||||||
termios = &state.Termios
|
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) {
|
func getState(fd uintptr) (*State, error) {
|
||||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{state{Termios: *termios}}, nil
|
return &State{state{Termios: *termios}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func restore(fd uintptr, state *State) error {
|
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) {
|
func getSize(fd uintptr) (width, height int, err error) {
|
||||||
ws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
ws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
return int(ws.Col), int(ws.Row), nil
|
return int(ws.Col), int(ws.Row), nil
|
||||||
}
|
}
|
||||||
@ -73,13 +73,13 @@ func getSize(fd uintptr) (width, height int, err error) {
|
|||||||
type passwordReader int
|
type passwordReader int
|
||||||
|
|
||||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
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) {
|
func readPassword(fd uintptr) ([]byte, error) {
|
||||||
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := *termios
|
newState := *termios
|
||||||
@ -87,10 +87,10 @@ func readPassword(fd uintptr) ([]byte, error) {
|
|||||||
newState.Lflag |= unix.ICANON | unix.ISIG
|
newState.Lflag |= unix.ICANON | unix.ISIG
|
||||||
newState.Iflag |= unix.ICRNL
|
newState.Iflag |= unix.ICRNL
|
||||||
if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &newState); err != nil {
|
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))
|
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 {
|
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
||||||
return nil, err
|
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
|
raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||||
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
|
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
|
||||||
return nil, err
|
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 {
|
if err == io.EOF && len(ret) > 0 {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
return ret, err
|
return ret, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/clipperhouse/displaywidth/.gitignore
generated
vendored
Normal file
1
vendor/github.com/clipperhouse/displaywidth/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.DS_Store
|
||||||
37
vendor/github.com/clipperhouse/displaywidth/AGENTS.md
generated
vendored
Normal file
37
vendor/github.com/clipperhouse/displaywidth/AGENTS.md
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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 to retrieve details,
|
||||||
|
or post comments. Then, compare the current branch with main. Reviewing a PR
|
||||||
|
and reviewing a branch are about the same, but the PR may add context.
|
||||||
|
|
||||||
|
Look for bugs. Think like GitHub Copilot or Cursor BugBot.
|
||||||
|
|
||||||
|
Offer to post a brief summary of the review to the PR, via the gh CLI tool.
|
||||||
|
|
||||||
|
## 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.
|
||||||
49
vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md
generated
vendored
Normal file
49
vendor/github.com/clipperhouse/displaywidth/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [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
|
||||||
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 Brandon Fulljames
|
Copyright (c) 2025 Matt Sherman
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
123
vendor/github.com/clipperhouse/displaywidth/README.md
generated
vendored
Normal file
123
vendor/github.com/clipperhouse/displaywidth/README.md
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
You can specify East Asian Width settings. When false (default),
|
||||||
|
[East Asian Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous)
|
||||||
|
are treated as width 1. When true, East Asian Ambiguous characters are treated
|
||||||
|
as width 2.
|
||||||
|
|
||||||
|
```go
|
||||||
|
myOptions := displaywidth.Options{
|
||||||
|
EastAsianWidth: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
width := myOptions.String("Hello, 世界!")
|
||||||
|
fmt.Println(width)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technical details
|
||||||
|
|
||||||
|
This package implements the Unicode East Asian Width standard
|
||||||
|
([UAX #11](https://www.unicode.org/reports/tr11/)), 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://unicode.org/reports/tr51/).
|
||||||
|
|
||||||
|
`clipperhouse/displaywidth`, `mattn/go-runewidth`, and `rivo/uniseg` will
|
||||||
|
give the same outputs for most real-world text. See extensive details in the
|
||||||
|
[compatibility analysis](comparison/COMPATIBILITY_ANALYSIS.md).
|
||||||
|
|
||||||
|
If you wish to investigate the core logic, see the `lookupProperties` and `width`
|
||||||
|
functions in [width.go](width.go#L135). The essential trie generation logic is in
|
||||||
|
`buildPropertyBitmap` in [unicode.go](internal/gen/unicode.go#L317).
|
||||||
|
|
||||||
|
I (@clipperhouse) am keeping an eye on [emerging standards and test suites](https://www.jeffquast.com/post/state-of-terminal-emulation-2025/).
|
||||||
|
|
||||||
|
## 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 10929 ns/op 154.36 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_Mixed/mattn/go-runewidth-8 14540 ns/op 116.02 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_Mixed/rivo/uniseg-8 19751 ns/op 85.41 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkString_EastAsian/clipperhouse/displaywidth-8 10885 ns/op 154.98 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_EastAsian/mattn/go-runewidth-8 23969 ns/op 70.38 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_EastAsian/rivo/uniseg-8 19852 ns/op 84.98 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkString_ASCII/clipperhouse/displaywidth-8 1103 ns/op 116.01 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_ASCII/mattn/go-runewidth-8 1166 ns/op 109.79 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_ASCII/rivo/uniseg-8 1584 ns/op 80.83 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkString_Emoji/clipperhouse/displaywidth-8 3108 ns/op 232.93 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_Emoji/mattn/go-runewidth-8 4802 ns/op 150.76 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkString_Emoji/rivo/uniseg-8 6607 ns/op 109.58 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkRune_Mixed/clipperhouse/displaywidth-8 3456 ns/op 488.20 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRune_Mixed/mattn/go-runewidth-8 5400 ns/op 312.39 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkRune_EastAsian/clipperhouse/displaywidth-8 3475 ns/op 485.41 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRune_EastAsian/mattn/go-runewidth-8 15701 ns/op 107.44 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkRune_ASCII/clipperhouse/displaywidth-8 257.0 ns/op 498.13 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRune_ASCII/mattn/go-runewidth-8 266.4 ns/op 480.50 MB/s 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
BenchmarkRune_Emoji/clipperhouse/displaywidth-8 1384 ns/op 523.02 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRune_Emoji/mattn/go-runewidth-8 2273 ns/op 318.45 MB/s 0 B/op 0 allocs/op
|
||||||
|
```
|
||||||
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 .
|
||||||
1716
vendor/github.com/clipperhouse/displaywidth/trie.go
generated
vendored
Normal file
1716
vendor/github.com/clipperhouse/displaywidth/trie.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
210
vendor/github.com/clipperhouse/displaywidth/width.go
generated
vendored
Normal file
210
vendor/github.com/clipperhouse/displaywidth/width.go
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package displaywidth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/clipperhouse/stringish"
|
||||||
|
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// String calculates the display width of a string,
|
||||||
|
// by iterating over grapheme clusters in the string
|
||||||
|
// and summing their widths.
|
||||||
|
func String(s string) int {
|
||||||
|
return DefaultOptions.String(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes calculates the display width of a []byte,
|
||||||
|
// by iterating over grapheme clusters in the byte slice
|
||||||
|
// and summing their widths.
|
||||||
|
func Bytes(s []byte) int {
|
||||||
|
return DefaultOptions.Bytes(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rune calculates the display width of a rune. You
|
||||||
|
// should almost certainly use [String] or [Bytes] for
|
||||||
|
// most purposes.
|
||||||
|
//
|
||||||
|
// The smallest unit of display width is a grapheme
|
||||||
|
// cluster, not a rune. Iterating over runes to measure
|
||||||
|
// width is incorrect in most cases.
|
||||||
|
func Rune(r rune) int {
|
||||||
|
return DefaultOptions.Rune(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options allows you to specify the treatment of ambiguous East Asian
|
||||||
|
// characters. When EastAsianWidth is false (default), ambiguous East Asian
|
||||||
|
// characters are treated as width 1. When EastAsianWidth is true, ambiguous
|
||||||
|
// East Asian characters are treated as width 2.
|
||||||
|
type Options struct {
|
||||||
|
EastAsianWidth bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultOptions is the default options for the display width
|
||||||
|
// calculation, which is EastAsianWidth: false.
|
||||||
|
var DefaultOptions = Options{EastAsianWidth: false}
|
||||||
|
|
||||||
|
// String calculates the display width of a string,
|
||||||
|
// for the given options, by iterating over grapheme clusters
|
||||||
|
// and summing their widths.
|
||||||
|
func (options Options) String(s string) int {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
g := graphemes.FromString(s)
|
||||||
|
for g.Next() {
|
||||||
|
props := lookupProperties(g.Value())
|
||||||
|
total += props.width(options)
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes calculates the display width of a []byte,
|
||||||
|
// for the given options, by iterating over grapheme
|
||||||
|
// clusters in the byte slice and summing their widths.
|
||||||
|
func (options Options) Bytes(s []byte) int {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
g := graphemes.FromBytes(s)
|
||||||
|
for g.Next() {
|
||||||
|
props := lookupProperties(g.Value())
|
||||||
|
total += props.width(options)
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rune calculates the display width of a rune,
|
||||||
|
// for the given options.
|
||||||
|
//
|
||||||
|
// The smallest unit of display width is a grapheme
|
||||||
|
// cluster, not a rune. Iterating over runes to measure
|
||||||
|
// width is incorrect in most cases.
|
||||||
|
func (options Options) Rune(r rune) int {
|
||||||
|
// Fast path for ASCII
|
||||||
|
if r < utf8.RuneSelf {
|
||||||
|
if isASCIIControl(byte(r)) {
|
||||||
|
// Control (0x00-0x1F) and DEL (0x7F)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
// ASCII printable (0x20-0x7E)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surrogates (U+D800-U+DFFF) are invalid UTF-8 and have zero width
|
||||||
|
// Other packages might turn them into the replacement character (U+FFFD)
|
||||||
|
// in which case, we won't see it.
|
||||||
|
if r >= 0xD800 && r <= 0xDFFF {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack-allocated to avoid heap allocation
|
||||||
|
var buf [4]byte // UTF-8 is at most 4 bytes
|
||||||
|
n := utf8.EncodeRune(buf[:], r)
|
||||||
|
// Skip the grapheme iterator and directly lookup properties
|
||||||
|
props := lookupProperties(buf[:n])
|
||||||
|
return props.width(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isASCIIControl(b byte) bool {
|
||||||
|
return b < 0x20 || b == 0x7F
|
||||||
|
}
|
||||||
|
|
||||||
|
// isRIPrefix checks if the slice matches the Regional Indicator prefix
|
||||||
|
// (F0 9F 87). It assumes len(s) >= 3.
|
||||||
|
func isRIPrefix[T stringish.Interface](s T) bool {
|
||||||
|
return s[0] == 0xF0 && s[1] == 0x9F && s[2] == 0x87
|
||||||
|
}
|
||||||
|
|
||||||
|
// isVS16 checks if the slice matches VS16 (U+FE0F) UTF-8 encoding
|
||||||
|
// (EF B8 8F). It assumes len(s) >= 3.
|
||||||
|
func isVS16[T stringish.Interface](s T) bool {
|
||||||
|
return s[0] == 0xEF && s[1] == 0xB8 && s[2] == 0x8F
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupProperties returns the properties for the first character in a string
|
||||||
|
func lookupProperties[T stringish.Interface](s T) property {
|
||||||
|
l := len(s)
|
||||||
|
|
||||||
|
if l == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
b := s[0]
|
||||||
|
if isASCIIControl(b) {
|
||||||
|
return _Zero_Width
|
||||||
|
}
|
||||||
|
|
||||||
|
if b < utf8.RuneSelf {
|
||||||
|
// Check for variation selector after ASCII (e.g., keycap sequences like 1️⃣)
|
||||||
|
if l >= 4 {
|
||||||
|
// Subslice may help eliminate bounds checks
|
||||||
|
vs := s[1:4]
|
||||||
|
if isVS16(vs) {
|
||||||
|
// VS16 requests emoji presentation (width 2)
|
||||||
|
return _Emoji
|
||||||
|
}
|
||||||
|
// VS15 (0x8E) requests text presentation but does not affect width,
|
||||||
|
// in my reading of Unicode TR51. Falls through to _Default.
|
||||||
|
}
|
||||||
|
return _Default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regional indicator pair (flag)
|
||||||
|
if l >= 8 {
|
||||||
|
// Subslice may help eliminate bounds checks
|
||||||
|
ri := s[:8]
|
||||||
|
if isRIPrefix(ri[0:3]) {
|
||||||
|
b3 := ri[3]
|
||||||
|
if b3 >= 0xA6 && b3 <= 0xBF && isRIPrefix(ri[4:7]) {
|
||||||
|
b7 := ri[7]
|
||||||
|
if b7 >= 0xA6 && b7 <= 0xBF {
|
||||||
|
return _Emoji
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
props, size := lookup(s)
|
||||||
|
p := property(props)
|
||||||
|
|
||||||
|
// Variation Selectors
|
||||||
|
if size > 0 && l >= size+3 {
|
||||||
|
// Subslice may help eliminate bounds checks
|
||||||
|
vs := s[size : size+3]
|
||||||
|
if isVS16(vs) {
|
||||||
|
// VS16 requests emoji presentation (width 2)
|
||||||
|
return _Emoji
|
||||||
|
}
|
||||||
|
// VS15 (0x8E) requests text presentation but does not affect width,
|
||||||
|
// in my reading of Unicode TR51. Falls through to return the base
|
||||||
|
// character's property (p).
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Default property = 0
|
||||||
|
|
||||||
|
// a jump table of sorts, instead of a switch
|
||||||
|
var widthTable = [5]int{
|
||||||
|
_Default: 1,
|
||||||
|
_Zero_Width: 0,
|
||||||
|
_East_Asian_Wide: 2,
|
||||||
|
_East_Asian_Ambiguous: 1,
|
||||||
|
_Emoji: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// width determines the display width of a character based on its properties
|
||||||
|
// and configuration options
|
||||||
|
func (p property) width(options Options) int {
|
||||||
|
if options.EastAsianWidth && p == _East_Asian_Ambiguous {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return widthTable[p]
|
||||||
|
}
|
||||||
2
vendor/github.com/clipperhouse/stringish/.gitignore
generated
vendored
Normal file
2
vendor/github.com/clipperhouse/stringish/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.test
|
||||||
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Christian Muehlhaeuser
|
Copyright (c) 2025 Matt Sherman
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
64
vendor/github.com/clipperhouse/stringish/README.md
generated
vendored
Normal file
64
vendor/github.com/clipperhouse/stringish/README.md
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# stringish
|
||||||
|
|
||||||
|
A small Go module that provides a generic type constraint for “string-like”
|
||||||
|
data, and a utf8 package that works with both strings and byte slices
|
||||||
|
without conversions.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Interface interface {
|
||||||
|
~[]byte | ~string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/github.com/clipperhouse/stringish/utf8)
|
||||||
|
[](https://github.com/clipperhouse/stringish/actions/workflows/gotest.yml)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/clipperhouse/stringish
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/clipperhouse/stringish"
|
||||||
|
"github.com/clipperhouse/stringish/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
s := "Hello, 世界"
|
||||||
|
r, size := utf8.DecodeRune(s) // not DecodeRuneInString 🎉
|
||||||
|
|
||||||
|
b := []byte("Hello, 世界")
|
||||||
|
r, size = utf8.DecodeRune(b) // same API!
|
||||||
|
|
||||||
|
func MyFoo[T stringish.Interface](s T) T {
|
||||||
|
// pass a string or a []byte
|
||||||
|
// iterate, slice, transform, whatever
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Sometimes we want APIs to accept `string` or `[]byte` without having to convert
|
||||||
|
between those types. That conversion usually allocates!
|
||||||
|
|
||||||
|
By implementing with `stringish.Interface`, we can have a single API, and
|
||||||
|
single implementation for both types: one `Foo` instead of `Foo` and
|
||||||
|
`FooString`.
|
||||||
|
|
||||||
|
We have converted the
|
||||||
|
[`unicode/utf8` package](https://github.com/clipperhouse/stringish/blob/main/utf8/utf8.go)
|
||||||
|
as an example -- note the absence of`*InString` funcs. We might look at `x/text`
|
||||||
|
next.
|
||||||
|
|
||||||
|
## Used by
|
||||||
|
|
||||||
|
- clipperhouse/uax29: [stringish trie](https://github.com/clipperhouse/uax29/blob/master/graphemes/trie.go#L27), [stringish iterator](https://github.com/clipperhouse/uax29/blob/master/internal/iterators/iterator.go#L9), [stringish SplitFunc](https://github.com/clipperhouse/uax29/blob/master/graphemes/splitfunc.go#L21)
|
||||||
|
|
||||||
|
- [clipperhouse/displaywidth](https://github.com/clipperhouse/displaywidth)
|
||||||
|
|
||||||
|
## Prior discussion
|
||||||
|
|
||||||
|
- [Consideration of similar by the Go team](https://github.com/golang/go/issues/48643)
|
||||||
5
vendor/github.com/clipperhouse/stringish/interface.go
generated
vendored
Normal file
5
vendor/github.com/clipperhouse/stringish/interface.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package stringish
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
~[]byte | ~string
|
||||||
|
}
|
||||||
24
vendor/github.com/clipperhouse/uax29/v2/graphemes/README.md
generated
vendored
24
vendor/github.com/clipperhouse/uax29/v2/graphemes/README.md
generated
vendored
@ -1,5 +1,9 @@
|
|||||||
An implementation of grapheme cluster boundaries from [Unicode text segmentation](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) (UAX 29), for Unicode version 15.0.0.
|
An implementation of grapheme cluster boundaries from [Unicode text segmentation](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) (UAX 29), for Unicode version 15.0.0.
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/github.com/clipperhouse/uax29/v2/graphemes)
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -18,15 +22,14 @@ for tokens.Next() { // Next() returns true until end of data
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/clipperhouse/uax29/v2/graphemes)
|
|
||||||
|
|
||||||
_A grapheme is a “single visible character”, which might be a simple as a single letter, or a complex emoji that consists of several Unicode code points._
|
_A grapheme is a “single visible character”, which might be a simple as a single letter, or a complex emoji that consists of several Unicode code points._
|
||||||
|
|
||||||
## Conformance
|
## Conformance
|
||||||
|
|
||||||
We use the Unicode [test suite](https://unicode.org/reports/tr41/tr41-26.html#Tests29). Status:
|
We use the Unicode [test suite](https://unicode.org/reports/tr41/tr41-26.html#Tests29).
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## APIs
|
## APIs
|
||||||
|
|
||||||
@ -71,9 +74,18 @@ for tokens.Next() { // Next() returns true until end of data
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Performance
|
### Benchmarks
|
||||||
|
|
||||||
On a Mac M2 laptop, we see around 200MB/s, or around 100 million graphemes per second. You should see ~constant memory, and no allocations.
|
On a Mac M2 laptop, we see around 200MB/s, or around 100 million graphemes per second, and no allocations.
|
||||||
|
|
||||||
|
```
|
||||||
|
goos: darwin
|
||||||
|
goarch: arm64
|
||||||
|
pkg: github.com/clipperhouse/uax29/graphemes/comparative
|
||||||
|
cpu: Apple M2
|
||||||
|
BenchmarkGraphemes/clipperhouse/uax29-8 173805 ns/op 201.16 MB/s 0 B/op 0 allocs/op
|
||||||
|
BenchmarkGraphemes/rivo/uniseg-8 2045128 ns/op 17.10 MB/s 0 B/op 0 allocs/op
|
||||||
|
```
|
||||||
|
|
||||||
### Invalid inputs
|
### Invalid inputs
|
||||||
|
|
||||||
|
|||||||
7
vendor/github.com/clipperhouse/uax29/v2/graphemes/iterator.go
generated
vendored
7
vendor/github.com/clipperhouse/uax29/v2/graphemes/iterator.go
generated
vendored
@ -1,8 +1,11 @@
|
|||||||
package graphemes
|
package graphemes
|
||||||
|
|
||||||
import "github.com/clipperhouse/uax29/v2/internal/iterators"
|
import (
|
||||||
|
"github.com/clipperhouse/stringish"
|
||||||
|
"github.com/clipperhouse/uax29/v2/internal/iterators"
|
||||||
|
)
|
||||||
|
|
||||||
type Iterator[T iterators.Stringish] struct {
|
type Iterator[T stringish.Interface] struct {
|
||||||
*iterators.Iterator[T]
|
*iterators.Iterator[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
vendor/github.com/clipperhouse/uax29/v2/graphemes/splitfunc.go
generated
vendored
4
vendor/github.com/clipperhouse/uax29/v2/graphemes/splitfunc.go
generated
vendored
@ -3,7 +3,7 @@ package graphemes
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
|
||||||
"github.com/clipperhouse/uax29/v2/internal/iterators"
|
"github.com/clipperhouse/stringish"
|
||||||
)
|
)
|
||||||
|
|
||||||
// is determines if lookup intersects propert(ies)
|
// is determines if lookup intersects propert(ies)
|
||||||
@ -18,7 +18,7 @@ const _Ignore = _Extend
|
|||||||
// See https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries.
|
// See https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries.
|
||||||
var SplitFunc bufio.SplitFunc = splitFunc[[]byte]
|
var SplitFunc bufio.SplitFunc = splitFunc[[]byte]
|
||||||
|
|
||||||
func splitFunc[T iterators.Stringish](data T, atEOF bool) (advance int, token T, err error) {
|
func splitFunc[T stringish.Interface](data T, atEOF bool) (advance int, token T, err error) {
|
||||||
var empty T
|
var empty T
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, empty, nil
|
return 0, empty, nil
|
||||||
|
|||||||
6
vendor/github.com/clipperhouse/uax29/v2/graphemes/trie.go
generated
vendored
6
vendor/github.com/clipperhouse/uax29/v2/graphemes/trie.go
generated
vendored
@ -1,10 +1,10 @@
|
|||||||
package graphemes
|
package graphemes
|
||||||
|
|
||||||
|
import "github.com/clipperhouse/stringish"
|
||||||
|
|
||||||
// generated by github.com/clipperhouse/uax29/v2
|
// generated by github.com/clipperhouse/uax29/v2
|
||||||
// from https://www.unicode.org/Public/15.0.0/ucd/auxiliary/GraphemeBreakProperty.txt
|
// from https://www.unicode.org/Public/15.0.0/ucd/auxiliary/GraphemeBreakProperty.txt
|
||||||
|
|
||||||
import "github.com/clipperhouse/uax29/v2/internal/iterators"
|
|
||||||
|
|
||||||
type property uint16
|
type property uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,7 +27,7 @@ const (
|
|||||||
// lookup returns the trie value for the first UTF-8 encoding in s and
|
// lookup returns the trie value for the first UTF-8 encoding in s and
|
||||||
// the width in bytes of this encoding. The size will be 0 if s does not
|
// the width in bytes of this encoding. The size will be 0 if s does not
|
||||||
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
|
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
|
||||||
func lookup[T iterators.Stringish](s T) (v property, sz int) {
|
func lookup[T stringish.Interface](s T) (v property, sz int) {
|
||||||
c0 := s[0]
|
c0 := s[0]
|
||||||
switch {
|
switch {
|
||||||
case c0 < 0x80: // is ASCII
|
case c0 < 0x80: // is ASCII
|
||||||
|
|||||||
27
vendor/github.com/clipperhouse/uax29/v2/internal/iterators/iterator.go
generated
vendored
27
vendor/github.com/clipperhouse/uax29/v2/internal/iterators/iterator.go
generated
vendored
@ -1,14 +1,12 @@
|
|||||||
package iterators
|
package iterators
|
||||||
|
|
||||||
type Stringish interface {
|
import "github.com/clipperhouse/stringish"
|
||||||
[]byte | string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SplitFunc[T Stringish] func(T, bool) (int, T, error)
|
type SplitFunc[T stringish.Interface] func(T, bool) (int, T, error)
|
||||||
|
|
||||||
// Iterator is a generic iterator for words that are either []byte or string.
|
// Iterator is a generic iterator for words that are either []byte or string.
|
||||||
// Iterate while Next() is true, and access the word via Value().
|
// Iterate while Next() is true, and access the word via Value().
|
||||||
type Iterator[T Stringish] struct {
|
type Iterator[T stringish.Interface] struct {
|
||||||
split SplitFunc[T]
|
split SplitFunc[T]
|
||||||
data T
|
data T
|
||||||
start int
|
start int
|
||||||
@ -16,7 +14,7 @@ type Iterator[T Stringish] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Iterator for the given data and SplitFunc.
|
// New creates a new Iterator for the given data and SplitFunc.
|
||||||
func New[T Stringish](split SplitFunc[T], data T) *Iterator[T] {
|
func New[T stringish.Interface](split SplitFunc[T], data T) *Iterator[T] {
|
||||||
return &Iterator[T]{
|
return &Iterator[T]{
|
||||||
split: split,
|
split: split,
|
||||||
data: data,
|
data: data,
|
||||||
@ -83,3 +81,20 @@ func (iter *Iterator[T]) Reset() {
|
|||||||
iter.start = 0
|
iter.start = 0
|
||||||
iter.pos = 0
|
iter.pos = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iter *Iterator[T]) First() T {
|
||||||
|
if len(iter.data) == 0 {
|
||||||
|
return iter.data
|
||||||
|
}
|
||||||
|
advance, _, err := iter.split(iter.data, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if advance <= 0 {
|
||||||
|
panic("SplitFunc returned a zero or negative advance")
|
||||||
|
}
|
||||||
|
if advance > len(iter.data) {
|
||||||
|
panic("SplitFunc advanced beyond the end of the data")
|
||||||
|
}
|
||||||
|
return iter.data[:advance]
|
||||||
|
}
|
||||||
|
|||||||
4
vendor/github.com/cyphar/filepath-securejoin/.golangci.yml
generated
vendored
4
vendor/github.com/cyphar/filepath-securejoin/.golangci.yml
generated
vendored
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
version: "2"
|
version: "2"
|
||||||
|
|
||||||
|
run:
|
||||||
|
build-tags:
|
||||||
|
- libpathrs
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- asasalint
|
- asasalint
|
||||||
|
|||||||
90
vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
generated
vendored
90
vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
generated
vendored
@ -6,6 +6,92 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## [Unreleased] ##
|
## [Unreleased] ##
|
||||||
|
|
||||||
|
## [0.6.0] - 2025-11-03 ##
|
||||||
|
|
||||||
|
> By the Power of Greyskull!
|
||||||
|
|
||||||
|
While quite small code-wise, this release marks a very key point in the
|
||||||
|
development of filepath-securejoin.
|
||||||
|
|
||||||
|
filepath-securejoin was originally intended (back in 2017) to simply be a
|
||||||
|
single-purpose library that would take some common code used in container
|
||||||
|
runtimes (specifically, Docker's `FollowSymlinksInScope`) and make it more
|
||||||
|
general-purpose (with the eventual goals of it ending up in the Go stdlib).
|
||||||
|
|
||||||
|
Of course, I quickly discovered that this problem was actually far more
|
||||||
|
complicated to solve when dealing with racing attackers, which lead to me
|
||||||
|
developing `openat2(2)` and [libpathrs][]. I had originally planned for
|
||||||
|
libpathrs to completely replace filepath-securejoin "once it was ready" but in
|
||||||
|
the interim we needed to fix several race attacks in runc as part of security
|
||||||
|
advisories. Obviously we couldn't require the usage of a pre-0.1 Rust library
|
||||||
|
in runc so it was necessary to port bits of libpathrs into filepath-securejoin.
|
||||||
|
(Ironically the first prototypes of libpathrs were originally written in Go and
|
||||||
|
then rewritten to Rust, so the code in filepath-securejoin is actually Go code
|
||||||
|
that was rewritten to Rust then re-rewritten to Go.)
|
||||||
|
|
||||||
|
It then became clear that pure-Go libraries will likely not be willing to
|
||||||
|
require CGo for all of their builds, so it was necessary to accept that
|
||||||
|
filepath-securejoin will need to stay. As such, in v0.5.0 we provided more
|
||||||
|
pure-Go implementations of features from libpathrs but moved them into
|
||||||
|
`pathrs-lite` subpackage to clarify what purpose these helpers serve.
|
||||||
|
|
||||||
|
This release finally closes the loop and makes it so that pathrs-lite can
|
||||||
|
transparently use libpathrs (via a `libpathrs` build-tag). This means that
|
||||||
|
upstream libraries can use the pure Go version if they prefer, but downstreams
|
||||||
|
(either downstream library users or even downstream distributions) are able to
|
||||||
|
migrate to libpathrs for all usages of pathrs-lite in an entire Go binary.
|
||||||
|
|
||||||
|
I should make it clear that I do not plan to port the rest of libpathrs to Go,
|
||||||
|
as I do not wish to maintain two copies of the same codebase. pathrs-lite
|
||||||
|
already provides the core essentials necessary to operate on paths safely for
|
||||||
|
most modern systems. Users who want additional hardening or more ergonomic APIs
|
||||||
|
are free to use [`cyphar.com/go-pathrs`][go-pathrs] (libpathrs's Go bindings).
|
||||||
|
|
||||||
|
[libpathrs]: https://github.com/cyphar/libpathrs
|
||||||
|
[go-pathrs]: https://cyphar.com/go-pathrs
|
||||||
|
|
||||||
|
### Breaking ###
|
||||||
|
- The deprecated `MkdirAll`, `MkdirAllHandle`, `OpenInRoot`, `OpenatInRoot` and
|
||||||
|
`Reopen` wrappers have been removed. Please switch to using `pathrs-lite`
|
||||||
|
directly.
|
||||||
|
|
||||||
|
### Added ###
|
||||||
|
- `pathrs-lite` now has support for using [libpathrs][libpathrs] as a backend.
|
||||||
|
This is opt-in and can be enabled at build time with the `libpathrs` build
|
||||||
|
tag. The intention is to allow for downstream libraries and other projects to
|
||||||
|
make use of the pure-Go `github.com/cyphar/filepath-securejoin/pathrs-lite`
|
||||||
|
package and distributors can then opt-in to using `libpathrs` for the entire
|
||||||
|
binary if they wish.
|
||||||
|
|
||||||
|
## [0.5.1] - 2025-10-31 ##
|
||||||
|
|
||||||
|
> Spooky scary skeletons send shivers down your spine!
|
||||||
|
|
||||||
|
### Changed ###
|
||||||
|
- `openat2` can return `-EAGAIN` if it detects a possible attack in certain
|
||||||
|
scenarios (namely if there was a rename or mount while walking a path with a
|
||||||
|
`..` component). While this is necessary to avoid a denial-of-service in the
|
||||||
|
kernel, it does require retry loops in userspace.
|
||||||
|
|
||||||
|
In previous versions, `pathrs-lite` would retry `openat2` 32 times before
|
||||||
|
returning an error, but we've received user reports that this limit can be
|
||||||
|
hit on systems with very heavy load. In some synthetic benchmarks (testing
|
||||||
|
the worst-case of an attacker doing renames in a tight loop on every core of
|
||||||
|
a 16-core machine) we managed to get a ~3% failure rate in runc. We have
|
||||||
|
improved this situation in two ways:
|
||||||
|
|
||||||
|
* We have now increased this limit to 128, which should be good enough for
|
||||||
|
most use-cases without becoming a denial-of-service vector (the number of
|
||||||
|
syscalls called by the `O_PATH` resolver in a typical case is within the
|
||||||
|
same ballpark). The same benchmarks show a failure rate of ~0.12% which
|
||||||
|
(while not zero) is probably sufficient for most users.
|
||||||
|
|
||||||
|
* In addition, we now return a `unix.EAGAIN` error that is bubbled up and can
|
||||||
|
be detected by callers. This means that callers with stricter requirements
|
||||||
|
to avoid spurious errors can choose to do their own infinite `EAGAIN` retry
|
||||||
|
loop (though we would strongly recommend users use time-based deadlines in
|
||||||
|
such retry loops to avoid potentially unbounded denials-of-service).
|
||||||
|
|
||||||
## [0.5.0] - 2025-09-26 ##
|
## [0.5.0] - 2025-09-26 ##
|
||||||
|
|
||||||
> Let the past die. Kill it if you have to.
|
> Let the past die. Kill it if you have to.
|
||||||
@ -354,7 +440,9 @@ This is our first release of `github.com/cyphar/filepath-securejoin`,
|
|||||||
containing a full implementation with a coverage of 93.5% (the only missing
|
containing a full implementation with a coverage of 93.5% (the only missing
|
||||||
cases are the error cases, which are hard to mocktest at the moment).
|
cases are the error cases, which are hard to mocktest at the moment).
|
||||||
|
|
||||||
[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.0...HEAD
|
[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.6.0...HEAD
|
||||||
|
[0.6.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.1...v0.6.0
|
||||||
|
[0.5.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.0...v0.5.1
|
||||||
[0.5.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...v0.5.0
|
[0.5.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...v0.5.0
|
||||||
[0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1
|
[0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1
|
||||||
[0.4.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...v0.4.0
|
[0.4.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...v0.4.0
|
||||||
|
|||||||
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
@ -1 +1 @@
|
|||||||
0.5.0
|
0.6.0
|
||||||
|
|||||||
48
vendor/github.com/cyphar/filepath-securejoin/deprecated_linux.go
generated
vendored
48
vendor/github.com/cyphar/filepath-securejoin/deprecated_linux.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package securejoin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// MkdirAll is a wrapper around [pathrs.MkdirAll].
|
|
||||||
//
|
|
||||||
// Deprecated: You should use [pathrs.MkdirAll] directly instead. This
|
|
||||||
// wrapper will be removed in filepath-securejoin v0.6.
|
|
||||||
MkdirAll = pathrs.MkdirAll
|
|
||||||
|
|
||||||
// MkdirAllHandle is a wrapper around [pathrs.MkdirAllHandle].
|
|
||||||
//
|
|
||||||
// Deprecated: You should use [pathrs.MkdirAllHandle] directly instead.
|
|
||||||
// This wrapper will be removed in filepath-securejoin v0.6.
|
|
||||||
MkdirAllHandle = pathrs.MkdirAllHandle
|
|
||||||
|
|
||||||
// OpenInRoot is a wrapper around [pathrs.OpenInRoot].
|
|
||||||
//
|
|
||||||
// Deprecated: You should use [pathrs.OpenInRoot] directly instead. This
|
|
||||||
// wrapper will be removed in filepath-securejoin v0.6.
|
|
||||||
OpenInRoot = pathrs.OpenInRoot
|
|
||||||
|
|
||||||
// OpenatInRoot is a wrapper around [pathrs.OpenatInRoot].
|
|
||||||
//
|
|
||||||
// Deprecated: You should use [pathrs.OpenatInRoot] directly instead. This
|
|
||||||
// wrapper will be removed in filepath-securejoin v0.6.
|
|
||||||
OpenatInRoot = pathrs.OpenatInRoot
|
|
||||||
|
|
||||||
// Reopen is a wrapper around [pathrs.Reopen].
|
|
||||||
//
|
|
||||||
// Deprecated: You should use [pathrs.Reopen] directly instead. This
|
|
||||||
// wrapper will be removed in filepath-securejoin v0.6.
|
|
||||||
Reopen = pathrs.Reopen
|
|
||||||
)
|
|
||||||
33
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md
generated
vendored
33
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
## `pathrs-lite` ##
|
|
||||||
|
|
||||||
`github.com/cyphar/filepath-securejoin/pathrs-lite` provides a minimal **pure
|
|
||||||
Go** implementation of the core bits of [libpathrs][]. This is not intended to
|
|
||||||
be a complete replacement for libpathrs, instead it is mainly intended to be
|
|
||||||
useful as a transition tool for existing Go projects.
|
|
||||||
|
|
||||||
The long-term plan for `pathrs-lite` is to provide a build tag that will cause
|
|
||||||
all `pathrs-lite` operations to call into libpathrs directly, thus removing
|
|
||||||
code duplication for projects that wish to make use of libpathrs (and providing
|
|
||||||
the ability for software packagers to opt-in to libpathrs support without
|
|
||||||
needing to patch upstream).
|
|
||||||
|
|
||||||
[libpathrs]: https://github.com/cyphar/libpathrs
|
|
||||||
|
|
||||||
### License ###
|
|
||||||
|
|
||||||
Most of this subpackage is licensed under the Mozilla Public License (version
|
|
||||||
2.0). For more information, see the top-level [COPYING.md][] and
|
|
||||||
[LICENSE.MPL-2.0][] files, as well as the individual license headers for each
|
|
||||||
file.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
```
|
|
||||||
|
|
||||||
[COPYING.md]: ../COPYING.md
|
|
||||||
[LICENSE.MPL-2.0]: ../LICENSE.MPL-2.0
|
|
||||||
14
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go
generated
vendored
14
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
// Package pathrs (pathrs-lite) is a less complete pure Go implementation of
|
|
||||||
// some of the APIs provided by [libpathrs].
|
|
||||||
package pathrs
|
|
||||||
30
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/assert/assert.go
generated
vendored
30
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/assert/assert.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Copyright (C) 2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
// Package assert provides some basic assertion helpers for Go.
|
|
||||||
package assert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Assert panics if the predicate is false with the provided argument.
|
|
||||||
func Assert(predicate bool, msg any) {
|
|
||||||
if !predicate {
|
|
||||||
panic(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assertf panics if the predicate is false and formats the message using the
|
|
||||||
// same formatting as [fmt.Printf].
|
|
||||||
//
|
|
||||||
// [fmt.Printf]: https://pkg.go.dev/fmt#Printf
|
|
||||||
func Assertf(predicate bool, fmtMsg string, args ...any) {
|
|
||||||
Assert(predicate, fmt.Sprintf(fmtMsg, args...))
|
|
||||||
}
|
|
||||||
30
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/errors.go
generated
vendored
30
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/errors.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
// Package internal contains unexported common code for filepath-securejoin.
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrPossibleAttack indicates that some attack was detected.
|
|
||||||
ErrPossibleAttack = errors.New("possible attack detected")
|
|
||||||
|
|
||||||
// ErrPossibleBreakout indicates that during an operation we ended up in a
|
|
||||||
// state that could be a breakout but we detected it.
|
|
||||||
ErrPossibleBreakout = errors.New("possible breakout detected")
|
|
||||||
|
|
||||||
// ErrInvalidDirectory indicates an unlinked directory.
|
|
||||||
ErrInvalidDirectory = errors.New("wandered into deleted directory")
|
|
||||||
|
|
||||||
// ErrDeletedInode indicates an unlinked file (non-directory).
|
|
||||||
ErrDeletedInode = errors.New("cannot verify path of deleted inode")
|
|
||||||
)
|
|
||||||
148
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/at_linux.go
generated
vendored
148
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/at_linux.go
generated
vendored
@ -1,148 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package fd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat"
|
|
||||||
)
|
|
||||||
|
|
||||||
// prepareAtWith returns -EBADF (an invalid fd) if dir is nil, otherwise using
|
|
||||||
// the dir.Fd(). We use -EBADF because in filepath-securejoin we generally
|
|
||||||
// don't want to allow relative-to-cwd paths. The returned path is an
|
|
||||||
// *informational* string that describes a reasonable pathname for the given
|
|
||||||
// *at(2) arguments. You must not use the full path for any actual filesystem
|
|
||||||
// operations.
|
|
||||||
func prepareAt(dir Fd, path string) (dirFd int, unsafeUnmaskedPath string) {
|
|
||||||
dirFd, dirPath := -int(unix.EBADF), "."
|
|
||||||
if dir != nil {
|
|
||||||
dirFd, dirPath = int(dir.Fd()), dir.Name()
|
|
||||||
}
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
// only prepend the dirfd path for relative paths
|
|
||||||
path = dirPath + "/" + path
|
|
||||||
}
|
|
||||||
// NOTE: If path is "." or "", the returned path won't be filepath.Clean,
|
|
||||||
// but that's okay since this path is either used for errors (in which case
|
|
||||||
// a trailing "/" or "/." is important information) or will be
|
|
||||||
// filepath.Clean'd later (in the case of fd.Openat).
|
|
||||||
return dirFd, path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Openat is an [Fd]-based wrapper around unix.Openat.
|
|
||||||
func Openat(dir Fd, path string, flags int, mode int) (*os.File, error) { //nolint:unparam // wrapper func
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
// Make sure we always set O_CLOEXEC.
|
|
||||||
flags |= unix.O_CLOEXEC
|
|
||||||
fd, err := unix.Openat(dirFd, path, flags, uint32(mode))
|
|
||||||
if err != nil {
|
|
||||||
return nil, &os.PathError{Op: "openat", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
// openat is only used with lexically-safe paths so we can use
|
|
||||||
// filepath.Clean here, and also the path itself is not going to be used
|
|
||||||
// for actual path operations.
|
|
||||||
fullPath = filepath.Clean(fullPath)
|
|
||||||
return os.NewFile(uintptr(fd), fullPath), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fstatat is an [Fd]-based wrapper around unix.Fstatat.
|
|
||||||
func Fstatat(dir Fd, path string, flags int) (unix.Stat_t, error) {
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
var stat unix.Stat_t
|
|
||||||
if err := unix.Fstatat(dirFd, path, &stat, flags); err != nil {
|
|
||||||
return stat, &os.PathError{Op: "fstatat", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
return stat, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Faccessat is an [Fd]-based wrapper around unix.Faccessat.
|
|
||||||
func Faccessat(dir Fd, path string, mode uint32, flags int) error {
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
err := unix.Faccessat(dirFd, path, mode, flags)
|
|
||||||
if err != nil {
|
|
||||||
err = &os.PathError{Op: "faccessat", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Readlinkat is an [Fd]-based wrapper around unix.Readlinkat.
|
|
||||||
func Readlinkat(dir Fd, path string) (string, error) {
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
size := 4096
|
|
||||||
for {
|
|
||||||
linkBuf := make([]byte, size)
|
|
||||||
n, err := unix.Readlinkat(dirFd, path, linkBuf)
|
|
||||||
if err != nil {
|
|
||||||
return "", &os.PathError{Op: "readlinkat", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
if n != size {
|
|
||||||
return string(linkBuf[:n]), nil
|
|
||||||
}
|
|
||||||
// Possible truncation, resize the buffer.
|
|
||||||
size *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// STATX_MNT_ID_UNIQUE is provided in golang.org/x/sys@v0.20.0, but in order to
|
|
||||||
// avoid bumping the requirement for a single constant we can just define it
|
|
||||||
// ourselves.
|
|
||||||
_STATX_MNT_ID_UNIQUE = 0x4000 //nolint:revive // unix.* name
|
|
||||||
|
|
||||||
// We don't care which mount ID we get. The kernel will give us the unique
|
|
||||||
// one if it is supported. If the kernel doesn't support
|
|
||||||
// STATX_MNT_ID_UNIQUE, the bit is ignored and the returned request mask
|
|
||||||
// will only contain STATX_MNT_ID (if supported).
|
|
||||||
wantStatxMntMask = _STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID
|
|
||||||
)
|
|
||||||
|
|
||||||
var hasStatxMountID = gocompat.SyncOnceValue(func() bool {
|
|
||||||
var stx unix.Statx_t
|
|
||||||
err := unix.Statx(-int(unix.EBADF), "/", 0, wantStatxMntMask, &stx)
|
|
||||||
return err == nil && stx.Mask&wantStatxMntMask != 0
|
|
||||||
})
|
|
||||||
|
|
||||||
// GetMountID gets the mount identifier associated with the fd and path
|
|
||||||
// combination. It is effectively a wrapper around fetching
|
|
||||||
// STATX_MNT_ID{,_UNIQUE} with unix.Statx, but with a fallback to 0 if the
|
|
||||||
// kernel doesn't support the feature.
|
|
||||||
func GetMountID(dir Fd, path string) (uint64, error) {
|
|
||||||
// If we don't have statx(STATX_MNT_ID*) support, we can't do anything.
|
|
||||||
if !hasStatxMountID() {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
|
|
||||||
var stx unix.Statx_t
|
|
||||||
err := unix.Statx(dirFd, path, unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW, wantStatxMntMask, &stx)
|
|
||||||
if stx.Mask&wantStatxMntMask == 0 {
|
|
||||||
// It's not a kernel limitation, for some reason we couldn't get a
|
|
||||||
// mount ID. Assume it's some kind of attack.
|
|
||||||
err = fmt.Errorf("could not get mount id: %w", err)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return 0, &os.PathError{Op: "statx(STATX_MNT_ID_...)", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
return stx.Mnt_id, nil
|
|
||||||
}
|
|
||||||
55
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/fd.go
generated
vendored
55
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/fd.go
generated
vendored
@ -1,55 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Copyright (C) 2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
// Package fd provides a drop-in interface-based replacement of [*os.File] that
|
|
||||||
// allows for things like noop-Close wrappers to be used.
|
|
||||||
//
|
|
||||||
// [*os.File]: https://pkg.go.dev/os#File
|
|
||||||
package fd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fd is an interface that mirrors most of the API of [*os.File], allowing you
|
|
||||||
// to create wrappers that can be used in place of [*os.File].
|
|
||||||
//
|
|
||||||
// [*os.File]: https://pkg.go.dev/os#File
|
|
||||||
type Fd interface {
|
|
||||||
io.Closer
|
|
||||||
Name() string
|
|
||||||
Fd() uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile-time interface checks.
|
|
||||||
var (
|
|
||||||
_ Fd = (*os.File)(nil)
|
|
||||||
_ Fd = noClose{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type noClose struct{ inner Fd }
|
|
||||||
|
|
||||||
func (f noClose) Name() string { return f.inner.Name() }
|
|
||||||
func (f noClose) Fd() uintptr { return f.inner.Fd() }
|
|
||||||
|
|
||||||
func (f noClose) Close() error { return nil }
|
|
||||||
|
|
||||||
// NopCloser returns an [*os.File]-like object where the [Close] method is now
|
|
||||||
// a no-op.
|
|
||||||
//
|
|
||||||
// Note that for [*os.File] and similar objects, the Go garbage collector will
|
|
||||||
// still call [Close] on the underlying file unless you use
|
|
||||||
// [runtime.SetFinalizer] to disable this behaviour. This is up to the caller
|
|
||||||
// to do (if necessary).
|
|
||||||
//
|
|
||||||
// [*os.File]: https://pkg.go.dev/os#File
|
|
||||||
// [Close]: https://pkg.go.dev/io#Closer
|
|
||||||
// [runtime.SetFinalizer]: https://pkg.go.dev/runtime#SetFinalizer
|
|
||||||
func NopCloser(f Fd) Fd { return noClose{inner: f} }
|
|
||||||
78
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/fd_linux.go
generated
vendored
78
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/fd_linux.go
generated
vendored
@ -1,78 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package fd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DupWithName creates a new file descriptor referencing the same underlying
|
|
||||||
// file, but with the provided name instead of fd.Name().
|
|
||||||
func DupWithName(fd Fd, name string) (*os.File, error) {
|
|
||||||
fd2, err := unix.FcntlInt(fd.Fd(), unix.F_DUPFD_CLOEXEC, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, os.NewSyscallError("fcntl(F_DUPFD_CLOEXEC)", err)
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(fd)
|
|
||||||
return os.NewFile(uintptr(fd2), name), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dup creates a new file description referencing the same underlying file.
|
|
||||||
func Dup(fd Fd) (*os.File, error) {
|
|
||||||
return DupWithName(fd, fd.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fstat is an [Fd]-based wrapper around unix.Fstat.
|
|
||||||
func Fstat(fd Fd) (unix.Stat_t, error) {
|
|
||||||
var stat unix.Stat_t
|
|
||||||
if err := unix.Fstat(int(fd.Fd()), &stat); err != nil {
|
|
||||||
return stat, &os.PathError{Op: "fstat", Path: fd.Name(), Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(fd)
|
|
||||||
return stat, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fstatfs is an [Fd]-based wrapper around unix.Fstatfs.
|
|
||||||
func Fstatfs(fd Fd) (unix.Statfs_t, error) {
|
|
||||||
var statfs unix.Statfs_t
|
|
||||||
if err := unix.Fstatfs(int(fd.Fd()), &statfs); err != nil {
|
|
||||||
return statfs, &os.PathError{Op: "fstatfs", Path: fd.Name(), Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(fd)
|
|
||||||
return statfs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDeadInode detects whether the file has been unlinked from a filesystem and
|
|
||||||
// is thus a "dead inode" from the kernel's perspective.
|
|
||||||
func IsDeadInode(file Fd) error {
|
|
||||||
// If the nlink of a file drops to 0, there is an attacker deleting
|
|
||||||
// directories during our walk, which could result in weird /proc values.
|
|
||||||
// It's better to error out in this case.
|
|
||||||
stat, err := Fstat(file)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("check for dead inode: %w", err)
|
|
||||||
}
|
|
||||||
if stat.Nlink == 0 {
|
|
||||||
err := internal.ErrDeletedInode
|
|
||||||
if stat.Mode&unix.S_IFMT == unix.S_IFDIR {
|
|
||||||
err = internal.ErrInvalidDirectory
|
|
||||||
}
|
|
||||||
return fmt.Errorf("%w %q", err, file.Name())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
54
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/mount_linux.go
generated
vendored
54
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/mount_linux.go
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package fd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fsopen is an [Fd]-based wrapper around unix.Fsopen.
|
|
||||||
func Fsopen(fsName string, flags int) (*os.File, error) {
|
|
||||||
// Make sure we always set O_CLOEXEC.
|
|
||||||
flags |= unix.FSOPEN_CLOEXEC
|
|
||||||
fd, err := unix.Fsopen(fsName, flags)
|
|
||||||
if err != nil {
|
|
||||||
return nil, os.NewSyscallError("fsopen "+fsName, err)
|
|
||||||
}
|
|
||||||
return os.NewFile(uintptr(fd), "fscontext:"+fsName), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fsmount is an [Fd]-based wrapper around unix.Fsmount.
|
|
||||||
func Fsmount(ctx Fd, flags, mountAttrs int) (*os.File, error) {
|
|
||||||
// Make sure we always set O_CLOEXEC.
|
|
||||||
flags |= unix.FSMOUNT_CLOEXEC
|
|
||||||
fd, err := unix.Fsmount(int(ctx.Fd()), flags, mountAttrs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, os.NewSyscallError("fsmount "+ctx.Name(), err)
|
|
||||||
}
|
|
||||||
return os.NewFile(uintptr(fd), "fsmount:"+ctx.Name()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenTree is an [Fd]-based wrapper around unix.OpenTree.
|
|
||||||
func OpenTree(dir Fd, path string, flags uint) (*os.File, error) {
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
// Make sure we always set O_CLOEXEC.
|
|
||||||
flags |= unix.OPEN_TREE_CLOEXEC
|
|
||||||
fd, err := unix.OpenTree(dirFd, path, flags)
|
|
||||||
if err != nil {
|
|
||||||
return nil, &os.PathError{Op: "open_tree", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
return os.NewFile(uintptr(fd), fullPath), nil
|
|
||||||
}
|
|
||||||
62
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go
generated
vendored
62
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go
generated
vendored
@ -1,62 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package fd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
func scopedLookupShouldRetry(how *unix.OpenHow, err error) bool {
|
|
||||||
// RESOLVE_IN_ROOT (and RESOLVE_BENEATH) can return -EAGAIN if we resolve
|
|
||||||
// ".." while a mount or rename occurs anywhere on the system. This could
|
|
||||||
// happen spuriously, or as the result of an attacker trying to mess with
|
|
||||||
// us during lookup.
|
|
||||||
//
|
|
||||||
// In addition, scoped lookups have a "safety check" at the end of
|
|
||||||
// complete_walk which will return -EXDEV if the final path is not in the
|
|
||||||
// root.
|
|
||||||
return how.Resolve&(unix.RESOLVE_IN_ROOT|unix.RESOLVE_BENEATH) != 0 &&
|
|
||||||
(errors.Is(err, unix.EAGAIN) || errors.Is(err, unix.EXDEV))
|
|
||||||
}
|
|
||||||
|
|
||||||
const scopedLookupMaxRetries = 32
|
|
||||||
|
|
||||||
// Openat2 is an [Fd]-based wrapper around unix.Openat2, but with some retry
|
|
||||||
// logic in case of EAGAIN errors.
|
|
||||||
func Openat2(dir Fd, path string, how *unix.OpenHow) (*os.File, error) {
|
|
||||||
dirFd, fullPath := prepareAt(dir, path)
|
|
||||||
// Make sure we always set O_CLOEXEC.
|
|
||||||
how.Flags |= unix.O_CLOEXEC
|
|
||||||
var tries int
|
|
||||||
for tries < scopedLookupMaxRetries {
|
|
||||||
fd, err := unix.Openat2(dirFd, path, how)
|
|
||||||
if err != nil {
|
|
||||||
if scopedLookupShouldRetry(how, err) {
|
|
||||||
// We retry a couple of times to avoid the spurious errors, and
|
|
||||||
// if we are being attacked then returning -EAGAIN is the best
|
|
||||||
// we can do.
|
|
||||||
tries++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: err}
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(dir)
|
|
||||||
return os.NewFile(uintptr(fd), fullPath), nil
|
|
||||||
}
|
|
||||||
return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: internal.ErrPossibleAttack}
|
|
||||||
}
|
|
||||||
10
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/README.md
generated
vendored
10
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/README.md
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
## gocompat ##
|
|
||||||
|
|
||||||
This directory contains backports of stdlib functions from later Go versions so
|
|
||||||
the filepath-securejoin can continue to be used by projects that are stuck with
|
|
||||||
Go 1.18 support. Note that often filepath-securejoin is added in security
|
|
||||||
patches for old releases, so avoiding the need to bump Go compiler requirements
|
|
||||||
is a huge plus to downstreams.
|
|
||||||
|
|
||||||
The source code is licensed under the same license as the Go stdlib. See the
|
|
||||||
source files for the precise license information.
|
|
||||||
13
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/doc.go
generated
vendored
13
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/doc.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
//go:build linux && go1.20
|
|
||||||
|
|
||||||
// Copyright (C) 2025 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package gocompat includes compatibility shims (backported from future Go
|
|
||||||
// stdlib versions) to permit filepath-securejoin to be used with older Go
|
|
||||||
// versions (often filepath-securejoin is added in security patches for old
|
|
||||||
// releases, so avoiding the need to bump Go compiler requirements is a huge
|
|
||||||
// plus to downstreams).
|
|
||||||
package gocompat
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
//go:build linux && go1.20
|
|
||||||
|
|
||||||
// Copyright (C) 2024 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package gocompat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
|
|
||||||
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
|
|
||||||
// is only guaranteed to give you baseErr.
|
|
||||||
func WrapBaseError(baseErr, extraErr error) error {
|
|
||||||
return fmt.Errorf("%w: %w", extraErr, baseErr)
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
//go:build linux && !go1.20
|
|
||||||
|
|
||||||
// Copyright (C) 2024 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package gocompat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type wrappedError struct {
|
|
||||||
inner error
|
|
||||||
isError error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err wrappedError) Is(target error) bool {
|
|
||||||
return err.isError == target
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err wrappedError) Unwrap() error {
|
|
||||||
return err.inner
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err wrappedError) Error() string {
|
|
||||||
return fmt.Sprintf("%v: %v", err.isError, err.inner)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
|
|
||||||
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
|
|
||||||
// is only guaranteed to give you baseErr.
|
|
||||||
func WrapBaseError(baseErr, extraErr error) error {
|
|
||||||
return wrappedError{
|
|
||||||
inner: baseErr,
|
|
||||||
isError: extraErr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
//go:build linux && go1.21
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package gocompat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"cmp"
|
|
||||||
"slices"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SlicesDeleteFunc is equivalent to Go 1.21's slices.DeleteFunc.
|
|
||||||
func SlicesDeleteFunc[S ~[]E, E any](slice S, delFn func(E) bool) S {
|
|
||||||
return slices.DeleteFunc(slice, delFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlicesContains is equivalent to Go 1.21's slices.Contains.
|
|
||||||
func SlicesContains[S ~[]E, E comparable](slice S, val E) bool {
|
|
||||||
return slices.Contains(slice, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlicesClone is equivalent to Go 1.21's slices.Clone.
|
|
||||||
func SlicesClone[S ~[]E, E any](slice S) S {
|
|
||||||
return slices.Clone(slice)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncOnceValue is equivalent to Go 1.21's sync.OnceValue.
|
|
||||||
func SyncOnceValue[T any](f func() T) func() T {
|
|
||||||
return sync.OnceValue(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncOnceValues is equivalent to Go 1.21's sync.OnceValues.
|
|
||||||
func SyncOnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
|
|
||||||
return sync.OnceValues(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmpOrdered is equivalent to Go 1.21's cmp.Ordered generic type definition.
|
|
||||||
type CmpOrdered = cmp.Ordered
|
|
||||||
|
|
||||||
// CmpCompare is equivalent to Go 1.21's cmp.Compare.
|
|
||||||
func CmpCompare[T CmpOrdered](x, y T) int {
|
|
||||||
return cmp.Compare(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max2 is equivalent to Go 1.21's max builtin (but only for two parameters).
|
|
||||||
func Max2[T CmpOrdered](x, y T) T {
|
|
||||||
return max(x, y)
|
|
||||||
}
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
//go:build linux && !go1.21
|
|
||||||
|
|
||||||
// Copyright (C) 2021, 2022 The Go Authors. All rights reserved.
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE.BSD file.
|
|
||||||
|
|
||||||
package gocompat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are very minimal implementations of functions that appear in Go 1.21's
|
|
||||||
// stdlib, included so that we can build on older Go versions. Most are
|
|
||||||
// borrowed directly from the stdlib, and a few are modified to be "obviously
|
|
||||||
// correct" without needing to copy too many other helpers.
|
|
||||||
|
|
||||||
// clearSlice is equivalent to Go 1.21's builtin clear.
|
|
||||||
// Copied from the Go 1.24 stdlib implementation.
|
|
||||||
func clearSlice[S ~[]E, E any](slice S) {
|
|
||||||
var zero E
|
|
||||||
for i := range slice {
|
|
||||||
slice[i] = zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// slicesIndexFunc is equivalent to Go 1.21's slices.IndexFunc.
|
|
||||||
// Copied from the Go 1.24 stdlib implementation.
|
|
||||||
func slicesIndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
|
|
||||||
for i := range s {
|
|
||||||
if f(s[i]) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlicesDeleteFunc is equivalent to Go 1.21's slices.DeleteFunc.
|
|
||||||
// Copied from the Go 1.24 stdlib implementation.
|
|
||||||
func SlicesDeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
|
|
||||||
i := slicesIndexFunc(s, del)
|
|
||||||
if i == -1 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
// Don't start copying elements until we find one to delete.
|
|
||||||
for j := i + 1; j < len(s); j++ {
|
|
||||||
if v := s[j]; !del(v) {
|
|
||||||
s[i] = v
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlicesContains is equivalent to Go 1.21's slices.Contains.
|
|
||||||
// Similar to the stdlib slices.Contains, except that we don't have
|
|
||||||
// slices.Index so we need to use slices.IndexFunc for this non-Func helper.
|
|
||||||
func SlicesContains[S ~[]E, E comparable](s S, v E) bool {
|
|
||||||
return slicesIndexFunc(s, func(e E) bool { return e == v }) >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlicesClone is equivalent to Go 1.21's slices.Clone.
|
|
||||||
// Copied from the Go 1.24 stdlib implementation.
|
|
||||||
func SlicesClone[S ~[]E, E any](s S) S {
|
|
||||||
// Preserve nil in case it matters.
|
|
||||||
if s == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return append(S([]E{}), s...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncOnceValue is equivalent to Go 1.21's sync.OnceValue.
|
|
||||||
// Copied from the Go 1.25 stdlib implementation.
|
|
||||||
func SyncOnceValue[T any](f func() T) func() T {
|
|
||||||
// Use a struct so that there's a single heap allocation.
|
|
||||||
d := struct {
|
|
||||||
f func() T
|
|
||||||
once sync.Once
|
|
||||||
valid bool
|
|
||||||
p any
|
|
||||||
result T
|
|
||||||
}{
|
|
||||||
f: f,
|
|
||||||
}
|
|
||||||
return func() T {
|
|
||||||
d.once.Do(func() {
|
|
||||||
defer func() {
|
|
||||||
d.f = nil
|
|
||||||
d.p = recover()
|
|
||||||
if !d.valid {
|
|
||||||
panic(d.p)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
d.result = d.f()
|
|
||||||
d.valid = true
|
|
||||||
})
|
|
||||||
if !d.valid {
|
|
||||||
panic(d.p)
|
|
||||||
}
|
|
||||||
return d.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncOnceValues is equivalent to Go 1.21's sync.OnceValues.
|
|
||||||
// Copied from the Go 1.25 stdlib implementation.
|
|
||||||
func SyncOnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
|
|
||||||
// Use a struct so that there's a single heap allocation.
|
|
||||||
d := struct {
|
|
||||||
f func() (T1, T2)
|
|
||||||
once sync.Once
|
|
||||||
valid bool
|
|
||||||
p any
|
|
||||||
r1 T1
|
|
||||||
r2 T2
|
|
||||||
}{
|
|
||||||
f: f,
|
|
||||||
}
|
|
||||||
return func() (T1, T2) {
|
|
||||||
d.once.Do(func() {
|
|
||||||
defer func() {
|
|
||||||
d.f = nil
|
|
||||||
d.p = recover()
|
|
||||||
if !d.valid {
|
|
||||||
panic(d.p)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
d.r1, d.r2 = d.f()
|
|
||||||
d.valid = true
|
|
||||||
})
|
|
||||||
if !d.valid {
|
|
||||||
panic(d.p)
|
|
||||||
}
|
|
||||||
return d.r1, d.r2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmpOrdered is equivalent to Go 1.21's cmp.Ordered generic type definition.
|
|
||||||
// Copied from the Go 1.25 stdlib implementation.
|
|
||||||
type CmpOrdered interface {
|
|
||||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
||||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
|
||||||
~float32 | ~float64 |
|
|
||||||
~string
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNaN reports whether x is a NaN without requiring the math package.
|
|
||||||
// This will always return false if T is not floating-point.
|
|
||||||
// Copied from the Go 1.25 stdlib implementation.
|
|
||||||
func isNaN[T CmpOrdered](x T) bool {
|
|
||||||
return x != x
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmpCompare is equivalent to Go 1.21's cmp.Compare.
|
|
||||||
// Copied from the Go 1.25 stdlib implementation.
|
|
||||||
func CmpCompare[T CmpOrdered](x, y T) int {
|
|
||||||
xNaN := isNaN(x)
|
|
||||||
yNaN := isNaN(y)
|
|
||||||
if xNaN {
|
|
||||||
if yNaN {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if yNaN {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
if x < y {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if x > y {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max2 is equivalent to Go 1.21's max builtin for two parameters.
|
|
||||||
func Max2[T CmpOrdered](x, y T) T {
|
|
||||||
m := x
|
|
||||||
if y > m {
|
|
||||||
m = y
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
@ -1,123 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
// Copyright (C) 2022 The Go Authors. All rights reserved.
|
|
||||||
// Copyright (C) 2025 SUSE LLC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE.BSD file.
|
|
||||||
|
|
||||||
// The parsing logic is very loosely based on the Go stdlib's
|
|
||||||
// src/internal/syscall/unix/kernel_version_linux.go but with an API that looks
|
|
||||||
// a bit like runc's libcontainer/system/kernelversion.
|
|
||||||
//
|
|
||||||
// TODO(cyphar): This API has been copied around to a lot of different projects
|
|
||||||
// (Docker, containerd, runc, and now filepath-securejoin) -- maybe we should
|
|
||||||
// put it in a separate project?
|
|
||||||
|
|
||||||
// Package kernelversion provides a simple mechanism for checking whether the
|
|
||||||
// running kernel is at least as new as some baseline kernel version. This is
|
|
||||||
// often useful when checking for features that would be too complicated to
|
|
||||||
// test support for (or in cases where we know that some kernel features in
|
|
||||||
// backport-heavy kernels are broken and need to be avoided).
|
|
||||||
package kernelversion
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KernelVersion is a numeric representation of the key numerical elements of a
|
|
||||||
// kernel version (for instance, "4.1.2-default-1" would be represented as
|
|
||||||
// KernelVersion{4, 1, 2}).
|
|
||||||
type KernelVersion []uint64
|
|
||||||
|
|
||||||
func (kver KernelVersion) String() string {
|
|
||||||
var str strings.Builder
|
|
||||||
for idx, elem := range kver {
|
|
||||||
if idx != 0 {
|
|
||||||
_, _ = str.WriteRune('.')
|
|
||||||
}
|
|
||||||
_, _ = str.WriteString(strconv.FormatUint(elem, 10))
|
|
||||||
}
|
|
||||||
return str.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidKernelVersion = errors.New("invalid kernel version")
|
|
||||||
|
|
||||||
// parseKernelVersion parses a string and creates a KernelVersion based on it.
|
|
||||||
func parseKernelVersion(kverStr string) (KernelVersion, error) {
|
|
||||||
kver := make(KernelVersion, 1, 3)
|
|
||||||
for idx, ch := range kverStr {
|
|
||||||
if '0' <= ch && ch <= '9' {
|
|
||||||
v := &kver[len(kver)-1]
|
|
||||||
*v = (*v * 10) + uint64(ch-'0')
|
|
||||||
} else {
|
|
||||||
if idx == 0 || kverStr[idx-1] < '0' || '9' < kverStr[idx-1] {
|
|
||||||
// "." must be preceded by a digit while in version section
|
|
||||||
return nil, fmt.Errorf("%w %q: kernel version has dot(s) followed by non-digit in version section", errInvalidKernelVersion, kverStr)
|
|
||||||
}
|
|
||||||
if ch != '.' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
kver = append(kver, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(kver) < 2 {
|
|
||||||
return nil, fmt.Errorf("%w %q: kernel versions must contain at least two components", errInvalidKernelVersion, kverStr)
|
|
||||||
}
|
|
||||||
return kver, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getKernelVersion gets the current kernel version.
|
|
||||||
var getKernelVersion = gocompat.SyncOnceValues(func() (KernelVersion, error) {
|
|
||||||
var uts unix.Utsname
|
|
||||||
if err := unix.Uname(&uts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Remove the \x00 from the release.
|
|
||||||
release := uts.Release[:]
|
|
||||||
return parseKernelVersion(string(release[:bytes.IndexByte(release, 0)]))
|
|
||||||
})
|
|
||||||
|
|
||||||
// GreaterEqualThan returns true if the the host kernel version is greater than
|
|
||||||
// or equal to the provided [KernelVersion]. When doing this comparison, any
|
|
||||||
// non-numerical suffixes of the host kernel version are ignored.
|
|
||||||
//
|
|
||||||
// If the number of components provided is not equal to the number of numerical
|
|
||||||
// components of the host kernel version, any missing components are treated as
|
|
||||||
// 0. This means that GreaterEqualThan(KernelVersion{4}) will be treated the
|
|
||||||
// same as GreaterEqualThan(KernelVersion{4, 0, 0, ..., 0, 0}), and that if the
|
|
||||||
// host kernel version is "4" then GreaterEqualThan(KernelVersion{4, 1}) will
|
|
||||||
// return false (because the host version will be treated as "4.0").
|
|
||||||
func GreaterEqualThan(wantKver KernelVersion) (bool, error) {
|
|
||||||
hostKver, err := getKernelVersion()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pad out the kernel version lengths to match one another.
|
|
||||||
cmpLen := gocompat.Max2(len(hostKver), len(wantKver))
|
|
||||||
hostKver = append(hostKver, make(KernelVersion, cmpLen-len(hostKver))...)
|
|
||||||
wantKver = append(wantKver, make(KernelVersion, cmpLen-len(wantKver))...)
|
|
||||||
|
|
||||||
for i := 0; i < cmpLen; i++ {
|
|
||||||
switch gocompat.CmpCompare(hostKver[i], wantKver[i]) {
|
|
||||||
case -1:
|
|
||||||
// host < want
|
|
||||||
return false, nil
|
|
||||||
case +1:
|
|
||||||
// host > want
|
|
||||||
return true, nil
|
|
||||||
case 0:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// equal version values
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
12
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/doc.go
generated
vendored
12
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/doc.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
// Package linux returns information about what features are supported on the
|
|
||||||
// running kernel.
|
|
||||||
package linux
|
|
||||||
47
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/mount_linux.go
generated
vendored
47
vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/mount_linux.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//go:build linux
|
|
||||||
|
|
||||||
// Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
// Copyright (C) 2024-2025 SUSE LLC
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
package linux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat"
|
|
||||||
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/kernelversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HasNewMountAPI returns whether the new fsopen(2) mount API is supported on
|
|
||||||
// the running kernel.
|
|
||||||
var HasNewMountAPI = gocompat.SyncOnceValue(func() bool {
|
|
||||||
// All of the pieces of the new mount API we use (fsopen, fsconfig,
|
|
||||||
// fsmount, open_tree) were added together in Linux 5.2[1,2], so we can
|
|
||||||
// just check for one of the syscalls and the others should also be
|
|
||||||
// available.
|
|
||||||
//
|
|
||||||
// Just try to use open_tree(2) to open a file without OPEN_TREE_CLONE.
|
|
||||||
// This is equivalent to openat(2), but tells us if open_tree is
|
|
||||||
// available (and thus all of the other basic new mount API syscalls).
|
|
||||||
// open_tree(2) is most light-weight syscall to test here.
|
|
||||||
//
|
|
||||||
// [1]: merge commit 400913252d09
|
|
||||||
// [2]: <https://lore.kernel.org/lkml/153754740781.17872.7869536526927736855.stgit@warthog.procyon.org.uk/>
|
|
||||||
fd, err := unix.OpenTree(-int(unix.EBADF), "/", unix.OPEN_TREE_CLOEXEC)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_ = unix.Close(fd)
|
|
||||||
|
|
||||||
// RHEL 8 has a backport of fsopen(2) that appears to have some very
|
|
||||||
// difficult to debug performance pathology. As such, it seems prudent to
|
|
||||||
// simply reject pre-5.2 kernels.
|
|
||||||
isNotBackport, _ := kernelversion.GreaterEqualThan(kernelversion.KernelVersion{5, 2})
|
|
||||||
return isNotBackport
|
|
||||||
})
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user