diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..69aeab9ae --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,8 @@ +version: "2" + +run: + timeout: 10m + +linters: + disable: + - govet \ No newline at end of file diff --git a/Makefile b/Makefile index 9a8ba3c81..6638ec72c 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,7 @@ fmt: # Run golangci-lint against code .PHONY: lint lint: $(TOOLS_BINDIR)/golangci-lint - "$(TOOLS_BINDIR)"/golangci-lint run -v --timeout 10m + "$(TOOLS_BINDIR)"/golangci-lint run -v .PHONY: renovate-check renovate-check: diff --git a/go.mod b/go.mod index 4eeafdd7c..20eca84d5 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/coocood/freecache v1.2.7 github.com/pulumi/pulumi-command/sdk v1.2.1 github.com/pulumi/pulumi-random/sdk/v4 v4.19.2 - github.com/pulumi/pulumi/sdk/v3 v3.232.0 + github.com/pulumi/pulumi/sdk/v3 v3.234.0 github.com/sirupsen/logrus v1.9.4 github.com/spf13/cobra v1.10.2 ) @@ -26,11 +26,11 @@ require ( github.com/aws/amazon-ec2-instance-selector/v3 v3.1.3 github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.17 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.299.1 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.300.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.100.1 github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 - github.com/pulumi/pulumi-aws-native/sdk v1.62.0 - github.com/pulumi/pulumi-aws/sdk/v7 v7.27.0 + github.com/pulumi/pulumi-aws-native/sdk v1.63.0 + github.com/pulumi/pulumi-aws/sdk/v7 v7.28.0 github.com/pulumi/pulumi-awsx/sdk/v3 v3.5.0 github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.17.0 github.com/pulumi/pulumi-azure-native-sdk/compute/v3 v3.17.0 @@ -102,7 +102,7 @@ require ( github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/charmbracelet/x/ansi v0.11.7 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect - github.com/charmbracelet/x/exp/golden v0.0.0-20260427100455-1ea3e7f8134f // indirect + github.com/charmbracelet/x/exp/golden v0.0.0-20260503005035-c113ba3d2310 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect @@ -137,7 +137,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/pgavlin/fx v0.1.6 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect + github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 // indirect github.com/pulumi/esc v0.23.0 // indirect @@ -152,7 +152,7 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/zclconf/go-cty v1.18.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/collector/featuregate v1.56.0 // indirect + go.opentelemetry.io/collector/featuregate v1.57.0 // indirect go.opentelemetry.io/collector/pdata v1.56.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect @@ -167,12 +167,12 @@ require ( golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/time v0.15.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.140.0 // indirect - k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f // indirect + k8s.io/kube-openapi v0.0.0-20260504175024-7bfe71ffdc10 // indirect k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect @@ -190,7 +190,7 @@ require ( github.com/cheggaaa/pb v1.0.29 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/go-git/go-billy/v5 v5.8.0 // indirect github.com/go-git/go-git/v5 v5.18.0 // indirect github.com/go-playground/validator/v10 v10.30.2 @@ -224,7 +224,7 @@ require ( golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect golang.org/x/text v0.36.0 // indirect - google.golang.org/grpc v1.80.0 // indirect + google.golang.org/grpc v1.81.0 // indirect google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index bce44a0d6..03f8aa002 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueO github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.299.1 h1:gQ9fSyFk3Y9Vm2fVbphBeJfXJlkJvEvC35TszBVjprg= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.299.1/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.300.0 h1:HgOfUy9Sm2Q9UQAyj9I/7NZhIaymTEakGA/FnLw65lw= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.300.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY= github.com/aws/aws-sdk-go-v2/service/ecs v1.79.1 h1:tQNU4tC4cMoZo1e+7J8j3/GWM7PJFdXCN0VzEFwFqUE= github.com/aws/aws-sdk-go-v2/service/ecs v1.79.1/go.mod h1:TIKZ9zIFS6W2k9FeW+r5sGVnlxp+aUt9oQ/St3Suj1o= github.com/aws/aws-sdk-go-v2/service/iam v1.53.10 h1:kcN3I3llO7VwIY5w3Pc5FmEonpsr23Ou7Cwk4qf7dik= @@ -121,8 +121,8 @@ github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dA github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= -github.com/charmbracelet/x/exp/golden v0.0.0-20260427100455-1ea3e7f8134f h1:W1dl4Koqo1MF76W+dX8gsryCBw2qoQjnU7v3+7oddhs= -github.com/charmbracelet/x/exp/golden v0.0.0-20260427100455-1ea3e7f8134f/go.mod h1:6fMpcW6iwN/kX+xJ52eqVWsDiBTe0UJD24JLoHFe+P0= +github.com/charmbracelet/x/exp/golden v0.0.0-20260503005035-c113ba3d2310 h1:qqdg2P7LPgzQXZLzwAghIJnDGLo+vjhwfhXTp+tYF5E= +github.com/charmbracelet/x/exp/golden v0.0.0-20260503005035-c113ba3d2310/go.mod h1:6fMpcW6iwN/kX+xJ52eqVWsDiBTe0UJD24JLoHFe+P0= 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/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= @@ -160,8 +160,8 @@ github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLg github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ= github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= @@ -193,8 +193,30 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1 github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= +github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= +github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= +github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= +github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= +github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= +github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= +github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= +github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= +github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= +github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= +github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= +github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= +github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= +github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= +github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= +github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -240,8 +262,6 @@ github.com/iwdgo/sigintwindows v0.2.2 h1:P6oWzpvV7MrEAmhUgs+zmarrWkyL77ycZz4v7+1 github.com/iwdgo/sigintwindows v0.2.2/go.mod h1:70wPb8oz8OnxPvsj2QMUjgIVhb8hMu5TUgX8KfFl7QY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY= @@ -268,8 +288,6 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4= github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -324,8 +342,8 @@ github.com/pgavlin/fx v0.1.6 h1:r9jEg69DhNoCd3Xh0+5mIbdbS3PqWrVWujkY76MFRTU= github.com/pgavlin/fx v0.1.6/go.mod h1:KWZJ6fqBBSh8GxHYqwYCf3rYE7Gp2p0N8tJp8xv9u9M= github.com/pgavlin/fx/v2 v2.0.12 h1:SjjaJ68Dt8Z4zHwOpY/RPijd7lShs6xYupJbF9ra00M= github.com/pgavlin/fx/v2 v2.0.12/go.mod h1:M/nF/ooAOy+NUBooYYXl2REARzJ/giPJxfMs8fINfKc= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= +github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= +github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -339,10 +357,10 @@ github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435 github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE= github.com/pulumi/esc v0.23.0 h1:5lOXO+5vvXOEQxXw7cTuYhjg9lVng23f9XNLWDR9EP4= github.com/pulumi/esc v0.23.0/go.mod h1:mkghIFn/TvN3XnP4jmCB4U5BG1I4UjGluARi39ckrCE= -github.com/pulumi/pulumi-aws-native/sdk v1.62.0 h1:VrxS/9bsvBU9rIFwpjWNqcgsV4BnovUmmk7OobNqrHc= -github.com/pulumi/pulumi-aws-native/sdk v1.62.0/go.mod h1:08HfiYFanToWN1uRzHgjoXUNGyzKG3vHthcmZ/a1s5A= -github.com/pulumi/pulumi-aws/sdk/v7 v7.27.0 h1:zMt6jWMMCN1MP/Wxa4CeDw1VcLiM0V4wTvLBRd8bywM= -github.com/pulumi/pulumi-aws/sdk/v7 v7.27.0/go.mod h1:MvfGxMurVnahZ4UtHSxvjuoytba7IsojtbsplqlXhdg= +github.com/pulumi/pulumi-aws-native/sdk v1.63.0 h1:dHb9Py3IPAi1RPwQbWcAs90y1Ytu65fQ3b5Zo+Riuoo= +github.com/pulumi/pulumi-aws-native/sdk v1.63.0/go.mod h1:08HfiYFanToWN1uRzHgjoXUNGyzKG3vHthcmZ/a1s5A= +github.com/pulumi/pulumi-aws/sdk/v7 v7.28.0 h1:dN3702SraCmSuSLXK5TJMQXvxq8HZGfE/4iCo9PKftk= +github.com/pulumi/pulumi-aws/sdk/v7 v7.28.0/go.mod h1:MvfGxMurVnahZ4UtHSxvjuoytba7IsojtbsplqlXhdg= github.com/pulumi/pulumi-awsx/sdk/v3 v3.5.0 h1:4yNWM2R0VrF7nG2D6BjBkrxZcR2XHz3M/tYUwOS/5OY= github.com/pulumi/pulumi-awsx/sdk/v3 v3.5.0/go.mod h1:2/RMtCM6nOYsWHV0rFZRze7PdSMIKM61ZHbDGEwMaOs= github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.17.0 h1:XQ4akM+v4jT6bUDrbzqty0YpwPJAbS/47QzfuAt6+MM= @@ -375,8 +393,8 @@ github.com/pulumi/pulumi-random/sdk/v4 v4.19.2 h1:YDGarxRPtAgpnUg7nXVe+gVfVABBjo github.com/pulumi/pulumi-random/sdk/v4 v4.19.2/go.mod h1:Dyyj49M9eX2ct1b3maqDGikMPVCNxXthG0KAhhj7nmI= github.com/pulumi/pulumi-tls/sdk/v5 v5.3.1 h1:qy6N1fKNNCH2ylIm+v0i4VWAHGMPVNnAaOTffzxSda8= github.com/pulumi/pulumi-tls/sdk/v5 v5.3.1/go.mod h1:HyK4UFDdneYjFKP02pa6Hk1CE0Af4eTWkhbw5gF7wkU= -github.com/pulumi/pulumi/sdk/v3 v3.232.0 h1:pU9j5qYHYtYZGaIKha1KFuB9ggp2obcMD1U523tpEnk= -github.com/pulumi/pulumi/sdk/v3 v3.232.0/go.mod h1:33NoTpvQXlTtAuaPbompgZNA3Ye4XEvxNydELFlWza8= +github.com/pulumi/pulumi/sdk/v3 v3.234.0 h1:PoXVM2lJoyqavwPQlVQC6KzhGKNOJpz9OFxyojm8RjA= +github.com/pulumi/pulumi/sdk/v3 v3.234.0/go.mod h1:Eu9QVad1cSPymhTboINPqK6WZMaW7I0NHQcWOmxLYek= 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= @@ -439,8 +457,8 @@ github.com/zclconf/go-cty v1.18.1 h1:yEGE8M4iIZlyKQURZNb2SnEyZlZHUcBCnx6KF81KuwM github.com/zclconf/go-cty v1.18.1/go.mod h1:qpnV6EDNgC1sns/AleL1fvatHw72j+S+nS+MJ+T2CSg= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/collector/featuregate v1.56.0 h1:NjcbOZkdCSXddAJmFLdO+pv1gmAgrU6sC5PBga2KlKI= -go.opentelemetry.io/collector/featuregate v1.56.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU= +go.opentelemetry.io/collector/featuregate v1.57.0 h1:KPDSUKYn6MHwgyGRSGPPcW/G96HH93pxuvvPwM+R8nY= +go.opentelemetry.io/collector/featuregate v1.57.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU= go.opentelemetry.io/collector/internal/testutil v0.150.0 h1:J4PLQGPfbLVaL5eI1aMc0m0TMixV9wzBhNhoHU00J0I= go.opentelemetry.io/collector/internal/testutil v0.150.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE= go.opentelemetry.io/collector/pdata v1.56.0 h1:W+QAfN2Iz8SNss1T5JNzRWFnw+7oP1vXBQH9ZuOJkXY= @@ -548,12 +566,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529 h1:zUWMZsvo/IJcD1t6MNCPO/azZTwz0TvwCBqr5aifoVY= -google.golang.org/genproto/googleapis/api v0.0.0-20260420184626-e10c466a9529/go.mod h1:a5OGAgyRr4lqco7AG9hQM9Fwh0N2ZV4grR0eXFEsXQg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 h1:U8orV30l6KpDsi9dxU0CoJZGbjS8EEpw+6ba+XwGPQA= +google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348/go.mod h1:Yzdzr5OOZFgSsEV2D/Xi9NL3bszpXFAg0hFJiRohcD8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -581,14 +599,14 @@ k8s.io/client-go v0.35.4 h1:DN6fyaGuzK64UvnKO5fOA6ymSjvfGAnCAHAR0C66kD8= k8s.io/client-go v0.35.4/go.mod h1:2Pg9WpsS4NeOpoYTfHHfMxBG8zFMSAUi4O/qoiJC3nY= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f h1:4Qiq0YAoQATdgmHALJWz9rJ4fj20pB3xebpB4CFNhYM= -k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/kube-openapi v0.0.0-20260504175024-7bfe71ffdc10 h1:WTqpjlNkK8rfPghVhuBPxEswk9Y99sUpiMAfOClcuNM= +k8s.io/kube-openapi v0.0.0-20260504175024-7bfe71ffdc10/go.mod h1:Cyq7UE0QtGe+Zo+/6XFrxiS4Mq0tLyQEONkFzSkfp9o= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= lukechampine.com/frand v1.5.1 h1:fg0eRtdmGFIxhP5zQJzM1lFDbD6CUfu/f+7WgAZd5/w= lukechampine.com/frand v1.5.1/go.mod h1:4VstaWc2plN4Mjr10chUD46RAVGWhpkZ5Nja8+Azp0Q= -pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= -pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= diff --git a/oci/Containerfile b/oci/Containerfile index 57c98660a..c4de64590 100644 --- a/oci/Containerfile +++ b/oci/Containerfile @@ -1,12 +1,12 @@ -FROM registry.access.redhat.com/ubi9/go-toolset@sha256:35f08031de19eb51d6b35ed62c6357d3529bc69a8db65cf623ea5f0b44051999 as builder +FROM registry.access.redhat.com/ubi9/go-toolset@sha256:59ec4752cf86f0d0dd240b9e29c64d6ee560c28fc986171e126db1db216a246a as builder ARG TARGETARCH USER root WORKDIR /workspace COPY . . # renovate: datasource=github-releases depName=pulumi/pulumi -ENV PULUMI_VERSION 3.232.0 +ENV PULUMI_VERSION 3.234.0 ENV PULUMI_BASE_URL="https://github.com/pulumi/pulumi/releases/download/v${PULUMI_VERSION}/pulumi-v${PULUMI_VERSION}" ENV PULUMI_URL="${PULUMI_BASE_URL}-linux-x64.tar.gz" @@ -19,7 +19,7 @@ RUN unset VERSION \ && tar -xzvf pulumicli.tar.gz # ubi 9.5-1732804088 -FROM registry.access.redhat.com/ubi9/ubi@sha256:fd3612ebe7968002122fb8c41df2cf9bd3f9916c573f7248113cdec1d6f4c245 +FROM registry.access.redhat.com/ubi9/ubi@sha256:38952545b5a9ddf145152f37b0da702d7d75fac1ddc52c5e14b03c7a77c51586 ARG TARGETARCH LABEL org.opencontainers.image.authors="Redhat Developer" @@ -32,7 +32,7 @@ ENV AWS_SDK_LOAD_CONFIG=1 \ # Pulumi plugins # renovate: datasource=github-releases depName=pulumi/pulumi-aws -ARG PULUMI_AWS_VERSION=v7.27.0 +ARG PULUMI_AWS_VERSION=v7.28.0 # renovate: datasource=github-releases depName=pulumi/pulumi-awsx ARG PULUMI_AWSX_VERSION=v3.5.0 # renovate: datasource=github-releases depName=pulumi/pulumi-azure-native @@ -44,7 +44,7 @@ ARG PULUMI_TLS_VERSION=v5.3.1 # renovate: datasource=github-releases depName=pulumi/pulumi-random ARG PULUMI_RANDOM_VERSION=v4.19.2 # renovate: datasource=github-releases depName=pulumi/pulumi-aws-native -ARG PULUMI_AWS_NATIVE_VERSION=v1.62.0 +ARG PULUMI_AWS_NATIVE_VERSION=v1.63.0 # renovate: datasource=github-releases depName=pulumi/pulumi-gitlab ARG PULUMI_GITLAB_VERSION=v9.11.0 diff --git a/tools/go.mod b/tools/go.mod index cbf513586..c18b6a4bb 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -8,19 +8,24 @@ replace ( github.com/charmbracelet/lipgloss/v2 => charm.land/lipgloss/v2 v2.0.3 ) -require github.com/golangci/golangci-lint/v2 v2.11.4 +require github.com/golangci/golangci-lint/v2 v2.12.1 -require ( - github.com/charmbracelet/x/cellbuf v0.0.15 // indirect - github.com/golangci/golines v0.15.0 // indirect -) +require github.com/golangci/golines v0.15.0 // indirect require ( - github.com/bombsimon/wsl/v5 v5.7.0 // indirect + charm.land/lipgloss/v2 v2.0.3 // indirect + github.com/ClickHouse/clickhouse-go-linter v1.2.0 // indirect + github.com/bombsimon/wsl/v5 v5.8.0 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318 // indirect + github.com/charmbracelet/x/termios v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - go-simpler.org/sloglint v0.11.1 // indirect + github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/ryancurrah/gomodguard/v2 v2.1.0 // indirect + go-simpler.org/sloglint v0.12.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect ) @@ -32,7 +37,6 @@ require ( github.com/alexkohler/prealloc v1.1.0 // indirect github.com/alfatraining/structtag v1.0.0 // indirect github.com/bombsimon/wsl/v4 v4.7.0 // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/godoc-lint/godoc-lint v0.11.2 // indirect github.com/golangci/asciicheck v0.5.0 // indirect @@ -55,9 +59,9 @@ require ( github.com/Antonboom/testifylint v1.6.4 // indirect github.com/BurntSushi/toml v1.6.0 // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect - github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/Masterminds/semver/v3 v3.5.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.23.1 // indirect + github.com/alecthomas/chroma/v2 v2.24.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect // github.com/alexkohler/prealloc v1.1.0 // indirect @@ -65,7 +69,6 @@ require ( github.com/alingse/nilnesserr v0.2.0 // indirect github.com/ashanbrown/forbidigo/v2 v2.3.1 // indirect github.com/ashanbrown/makezero/v2 v2.2.1 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect @@ -91,7 +94,7 @@ require ( github.com/fatih/color v1.19.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.6 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/ghostiam/protogetter v0.3.20 // indirect github.com/go-critic/go-critic v0.14.3 // indirect @@ -125,7 +128,6 @@ require ( github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jgautheron/goconst v1.10.0 // indirect - github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jjti/go-spancheck v0.6.5 // indirect github.com/julz/importas v0.2.0 // indirect github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect @@ -154,7 +156,6 @@ require ( github.com/mgechev/revive v1.15.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect @@ -180,7 +181,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/securego/gosec/v2 v2.25.0 // indirect + github.com/securego/gosec/v2 v2.26.1 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sonatard/noctx v0.5.1 // indirect @@ -214,7 +215,7 @@ require ( go.augendre.info/arangolint v0.4.0 // indirect go.augendre.info/fatcontext v0.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.1 // indirect + go.uber.org/zap v1.28.0 // indirect golang.org/x/exp/typeparams v0.0.0-20260410095643-746e56fc9e2f // indirect golang.org/x/mod v0.35.0 // indirect golang.org/x/sync v0.20.0 // indirect @@ -224,6 +225,6 @@ require ( google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.7.0 // indirect - mvdan.cc/gofumpt v0.9.2 // indirect + mvdan.cc/gofumpt v0.10.0 // indirect mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect ) diff --git a/tools/go.sum b/tools/go.sum index 56bf53957..5650e11cd 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -2,6 +2,8 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= +charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU= +charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA= codeberg.org/chavacava/garif v0.2.1 h1:K9oYxSlvlXrHXyW26Z4q61bTpJDo1wbvXcYKar/F/LM= codeberg.org/chavacava/garif v0.2.1/go.mod h1:oHnDSmc0f9K1MeE+MQD/yjkiIB5Xsn5y3S9Dg96Xk84= codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh2an7YmodI= @@ -26,18 +28,20 @@ github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS8 github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/ClickHouse/clickhouse-go-linter v1.2.0 h1:zbm174up3hTKjp0wKZVnTzRiG7tSF5XZF0FJG/MuCBI= +github.com/ClickHouse/clickhouse-go-linter v1.2.0/go.mod h1:pLorS7ffPTfuUV9M0SJgfHA/h/WQPQUk2FWG9x74cQ4= github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= -github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= -github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= +github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/MirrexOne/unqueryvet v1.5.4 h1:38QOxShO7JmMWT+eCdDMbcUgGCOeJphVkzzRgyLJgsQ= github.com/MirrexOne/unqueryvet v1.5.4/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= -github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= +github.com/alecthomas/chroma/v2 v2.24.1 h1:m5ffpfZbIb++k8AqFEKy9uVgY12xIQtBsQlc6DfZJQM= +github.com/alecthomas/chroma/v2 v2.24.1/go.mod h1:l+ohZ9xRXIbGe7cIW+YZgOGbvuVLjMps/FYN/CwuabI= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= @@ -56,8 +60,6 @@ github.com/ashanbrown/forbidigo/v2 v2.3.1 h1:KAZijvQ7zeIBKbhikT4jCm0TLYXC4u78bTi github.com/ashanbrown/forbidigo/v2 v2.3.1/go.mod h1:2QDkLTzU6TV937eFROamXrW92M3paehdae4HCDCOZCM= github.com/ashanbrown/makezero/v2 v2.2.1 h1:A7uU8dgB1PA9aelTxHMfHIQ8Qev8AB3JLxJUBUsejqM= github.com/ashanbrown/makezero/v2 v2.2.1/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY= -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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= @@ -66,8 +68,8 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= -github.com/bombsimon/wsl/v5 v5.7.0 h1:mIAmJm1wwNCt6ZvSLh8wrlDAYfTVH6doKjG0TZgbNKk= -github.com/bombsimon/wsl/v5 v5.7.0/go.mod h1:w6GRulXihJQKElcdEZbO3VDt23/KIfdRFBaTAAec0Lk= +github.com/bombsimon/wsl/v5 v5.8.0 h1:JTkyfs4yl8SPejrCF2GdABXE+mO1WvM7iUYzRWlsxDs= +github.com/bombsimon/wsl/v5 v5.8.0/go.mod h1:AbOLsulgkqP4ZnitHf9gwPtCOGlrzkk0jb0uNxRSY0o= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= @@ -86,14 +88,16 @@ github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1Di github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4= github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q= github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318 h1:OqDqxQZliC7C8adA7KjelW3OjtAxREfeHkNcd66wpeI= +github.com/charmbracelet/ultraviolet v0.0.0-20251205161215-1948445e3318/go.mod h1:Y6kE2GzHfkyQQVCSL9r2hwokSrIlHGzZG+71+wDYSZI= github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI= github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= -github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= -github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= +github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= +github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= +github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= @@ -126,8 +130,8 @@ github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47A github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.20 h1:oW7OPFit2FxZOpmMRPP9FffU4uUpfeE/rEdE1f+MzD0= @@ -136,8 +140,8 @@ github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOES github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474= +github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= @@ -177,8 +181,8 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.11.4 h1:GK+UlZBN5y7rh2PBnHA93XLSX6RaF7uhzJQ3JwU1wuA= -github.com/golangci/golangci-lint/v2 v2.11.4/go.mod h1:ODQDCASMA3VqfZYIbbQLpTRTzV7O/vjmIRF6u8NyFwI= +github.com/golangci/golangci-lint/v2 v2.12.1 h1:Rr07Ps/u+kvQqSO4L026WOSVvOlMU+RZTa/lossFaJA= +github.com/golangci/golangci-lint/v2 v2.12.1/go.mod h1:e/wBh0xvA13ag/OWByUmvjc9oYPtcKGpXycldJbc7t0= github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0= github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10= github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg= @@ -187,6 +191,8 @@ github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3H github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba h1:lqtcnSMDuuJdu/LrKWi5RJzpSNLOJXYe/nzQutTI5kg= +github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba/go.mod h1:sCBNcpRmhJCtbFGz49+IM3ETTFf7QdJ30AeYCd43NKk= github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= @@ -227,8 +233,6 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jgautheron/goconst v1.10.0 h1:Ptt+OoE4NaEWKhLrWrrN3IpZdGLiqaf7WLnEX/iv4Jw= github.com/jgautheron/goconst v1.10.0/go.mod h1:0p+wv1lFOiUr0IlNNT1nrm6+8DB8u2sU6KHGzFRXHDc= -github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= -github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= @@ -291,8 +295,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= -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/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= @@ -303,8 +307,8 @@ github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.23.0 h1:x3o4DGYOWbBMP/VdNQKgSj+25aJKx2Pe6lHr8gBcgf8= github.com/nunnatsa/ginkgolinter v0.23.0/go.mod h1:9qN1+0akwXEccwV1CAcCDfcoBlWXHB+ML9884pL4SZ4= -github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= +github.com/onsi/ginkgo/v2 v2.28.2 h1:DTrMfpqxiNUyQ3Y0zhn1n3cOO2euFgQPYIpkWwxVFps= +github.com/onsi/ginkgo/v2 v2.28.2/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= @@ -345,6 +349,8 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g= github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= +github.com/ryancurrah/gomodguard/v2 v2.1.0 h1:iIIARHe7Fsp10LY5utfMmYA++hkVuKsMFGDzxnVcijU= +github.com/ryancurrah/gomodguard/v2 v2.1.0/go.mod h1:ryDqr6as4otkNbUp/U0m7zAsxGpwcJ9NtL6mvy9Zzdw= github.com/ryanrolds/sqlclosecheck v0.6.0 h1:pEyL9okISdg1F1SEpJNlrEotkTGerv5BMk7U4AG0eVg= github.com/ryanrolds/sqlclosecheck v0.6.0/go.mod h1:xyX16hsDaCMXHrMJ3JMzGf5OpDfHTOTTQrT7HOFUmeU= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= @@ -357,8 +363,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= -github.com/securego/gosec/v2 v2.25.0 h1:8fN1/16qO0aA3ktgU9nDW5PdrCPd4vgpgaPM8ZE+aEA= -github.com/securego/gosec/v2 v2.25.0/go.mod h1:JjqD2HhHtH1GQYb2r2iYdqBihiA3wo5be9BED8+Uv5c= +github.com/securego/gosec/v2 v2.26.1 h1:gdkttGhQFVehqRJ8grKH4DrpqM/QlPKNHBnl8QgcEC4= +github.com/securego/gosec/v2 v2.26.1/go.mod h1:57UW4p0uoP3kxoTkhoo3axLdVAi+OWrLg/Ax/kdqtPE= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= @@ -429,7 +435,6 @@ github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= @@ -438,8 +443,8 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= -go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= -go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go-simpler.org/sloglint v0.12.0 h1:UzWDlLWNE5FLqsvyq3tWYHuQMbqrervOhT8qPl4Mmw4= +go-simpler.org/sloglint v0.12.0/go.mod h1:jBjjC2bm8rYrs88oTRlFX497kWjJsyZWYoNaXkGRI6I= go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50= go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA= go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= @@ -448,8 +453,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= -go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -467,7 +472,6 @@ golang.org/x/exp/typeparams v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:PqrXSW6 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -479,7 +483,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -500,9 +503,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -528,7 +529,6 @@ golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWc golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -552,7 +552,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= -mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= -mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= +mvdan.cc/gofumpt v0.10.0 h1:yGGpRS2pBN2OQIi7b21IXknJna7faPkFaVfHLrN6Euo= +mvdan.cc/gofumpt v0.10.0/go.mod h1:sU2ElXHzOEmvoPqfutYG7uunlueR4K2T1JFml40SzP4= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= diff --git a/tools/vendor/charm.land/lipgloss/v2/.editorconfig b/tools/vendor/charm.land/lipgloss/v2/.editorconfig new file mode 100644 index 000000000..5de2df8c5 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/.editorconfig @@ -0,0 +1,18 @@ +# https://editorconfig.org/ + +root = true + +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.go] +indent_style = tab +indent_size = 8 + +[*.golden] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/tools/vendor/charm.land/lipgloss/v2/.gitattributes b/tools/vendor/charm.land/lipgloss/v2/.gitattributes new file mode 100644 index 000000000..d5273520a --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/.gitattributes @@ -0,0 +1 @@ +*.golden linguist-generated=true -text diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/.gitignore b/tools/vendor/charm.land/lipgloss/v2/.gitignore similarity index 53% rename from tools/vendor/github.com/charmbracelet/lipgloss/.gitignore rename to tools/vendor/charm.land/lipgloss/v2/.gitignore index db482015d..3b478f575 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/.gitignore +++ b/tools/vendor/charm.land/lipgloss/v2/.gitignore @@ -1,2 +1,3 @@ ssh_example_ed25519* -dist/ +/tmp +**/.crush/** diff --git a/tools/vendor/charm.land/lipgloss/v2/.golangci.yml b/tools/vendor/charm.land/lipgloss/v2/.golangci.yml new file mode 100644 index 000000000..c90f03161 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/.golangci.yml @@ -0,0 +1,47 @@ +version: "2" +run: + tests: false +linters: + enable: + - bodyclose + - exhaustive + - goconst + - godot + - gomoddirectives + - goprintffuncname + - gosec + - misspell + - nakedret + - nestif + - nilerr + - noctx + - nolintlint + - prealloc + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace + - wrapcheck + exclusions: + rules: + - text: '(slog|log)\.\w+' + linters: + - noctx + generated: lax + presets: + - common-false-positives + settings: + exhaustive: + default-signifies-exhaustive: true +issues: + max-issues-per-linter: 0 + max-same-issues: 0 +formatters: + enable: + - gofumpt + - goimports + exclusions: + generated: lax diff --git a/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml b/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml new file mode 100644 index 000000000..c61970e07 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/.goreleaser.yml @@ -0,0 +1,5 @@ +includes: + - from_url: + url: charmbracelet/meta/main/goreleaser-lib.yaml +# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json + diff --git a/tools/vendor/charm.land/lipgloss/v2/LICENSE b/tools/vendor/charm.land/lipgloss/v2/LICENSE new file mode 100644 index 000000000..9f60dc1fc --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2026 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. diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/README.md b/tools/vendor/charm.land/lipgloss/v2/README.md similarity index 61% rename from tools/vendor/github.com/charmbracelet/lipgloss/README.md rename to tools/vendor/charm.land/lipgloss/v2/README.md index cee2371ce..4fda64003 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/README.md +++ b/tools/vendor/charm.land/lipgloss/v2/README.md @@ -1,23 +1,21 @@ # Lip Gloss -

- Lip Gloss title treatment
+

+
Latest Release - GoDoc + GoDoc Build Status - phorm.ai

-Style definitions for nice terminal layouts. Built with TUIs in mind. +

Style definitions for nice terminal layouts. Built with TUIs in mind.

-![Lip Gloss example](https://github.com/user-attachments/assets/7950b1c1-e0e3-427e-8e7d-6f7f6ad17ca7) +![Lip Gloss example](https://github.com/user-attachments/assets/92560e60-d70e-4ce0-b39e-a60bb933356b) Lip Gloss takes an expressive, declarative approach to terminal rendering. Users familiar with CSS will feel at home with Lip Gloss. ```go - -import "github.com/charmbracelet/lipgloss" +import "charm.land/lipgloss/v2" var style = lipgloss.NewStyle(). Bold(true). @@ -27,9 +25,20 @@ var style = lipgloss.NewStyle(). PaddingLeft(4). Width(22) -fmt.Println(style.Render("Hello, kitty")) +lipgloss.Println(style.Render("Hello, kitty")) +``` + +## Installation + +```bash +go get charm.land/lipgloss/v2 ``` +> [!TIP] +> +> Upgrading from v1? Check out the [upgrade guide](./UPGRADE_GUIDE_V2.md), or +> point your LLM at it and let it go to town. + ## Colors Lip Gloss supports the following color profiles: @@ -60,45 +69,58 @@ lipgloss.Color("#3C3C3C") // a dark gray ...as well as a 1-bit ASCII profile, which is black and white only. -The terminal's color profile will be automatically detected, and colors outside -the gamut of the current palette will be automatically coerced to their closest -available value. - -### Adaptive Colors - -You can also specify color options for light and dark backgrounds: +There are also named constants for the 16 standard ANSI colors: ```go -lipgloss.AdaptiveColor{Light: "236", Dark: "248"} +lipgloss.Black +lipgloss.Red +lipgloss.Green +lipgloss.Yellow +lipgloss.Blue +lipgloss.Magenta +lipgloss.Cyan +lipgloss.White +lipgloss.BrightBlack +lipgloss.BrightRed +lipgloss.BrightGreen +lipgloss.BrightYellow +lipgloss.BrightBlue +lipgloss.BrightMagenta +lipgloss.BrightCyan +lipgloss.BrightWhite ``` -The terminal's background color will automatically be detected and the -appropriate color will be chosen at runtime. +### Automatically Downsampling Colors -### Complete Colors +Some users don't have Truecolor terminals. Other times, output might not +support color at all (for example, in logs). Lip Gloss was designed to handle +this gracefully by automatically downsampling colors to the best available +profile. -CompleteColor specifies exact values for True Color, ANSI256, and ANSI color -profiles. +If you're using Lip Gloss with Bubble Tea, there’s nothing to do. If you're +using Lip Gloss standalone, just use `lipgloss.Println` or `lipgloss.Sprint` +(and their variants). -```go -lipgloss.CompleteColor{TrueColor: "#0000FF", ANSI256: "86", ANSI: "5"} -``` +For more, see [advanced color usage](#advanced-color-usage). -Automatic color degradation will not be performed in this case and it will be -based on the color specified. +### Color Utilities -### Complete Adaptive Colors - -You can use `CompleteColor` with `AdaptiveColor` to specify the exact values for -light and dark backgrounds without automatic color degradation. +Lip Gloss ships with a handful of handy tools for working with colors: ```go -lipgloss.CompleteAdaptiveColor{ - Light: CompleteColor{TrueColor: "#d7ffae", ANSI256: "193", ANSI: "11"}, - Dark: CompleteColor{TrueColor: "#d75fee", ANSI256: "163", ANSI: "5"}, -} +c := lipgloss.Color("#EB4268") // Sriracha sauce color +dark := lipgloss.Darken(c, 0.5) // dark Sriracha sauce +light := lipgloss.Lighten(c, 0.35) // light Sriracha sauce +green := lipgloss.Complementary(c) // greenish Sriracha sauce +withAlpha := lipgloss.Alpha(c, 0.2) // watered down Sriracha sauce ``` +### Advanced Color Tooling + +Lip Gloss also supports color blending, automatically choosing light or dark +variants of colors at runtime, and a lot more. For details, see [Advanced Color +Usage](#advanced-color-usage) and [the docs][docs]. + ## Inline Formatting Lip Gloss supports the usual ANSI text formatting options: @@ -114,6 +136,34 @@ var style = lipgloss.NewStyle(). Reverse(true) ``` +### Underline Styles + +Beyond simple on/off, underlines support multiple styles and custom colors: + +```go +s := lipgloss.NewStyle(). + UnderlineStyle(lipgloss.UnderlineCurly). + UnderlineColor(lipgloss.Color("#FF0000")) +``` + +Available styles: `UnderlineNone`, `UnderlineSingle`, `UnderlineDouble`, +`UnderlineCurly`, `UnderlineDotted`, `UnderlineDashed`. + +### Hyperlinks + +Styles can render clickable hyperlinks in supporting terminals: + +```go +s := lipgloss.NewStyle(). + Foreground(lipgloss.Color("#7B2FBE")). + Hyperlink("https://charm.land") + +lipgloss.Println(s.Render("Visit Charm")) +``` + +In unsupported terminals this will degrade gracefully and hyperlinks will +simply not render. + ## Block-Level Formatting Lip Gloss also supports rules for block-level formatting: @@ -152,6 +202,16 @@ lipgloss.NewStyle().Padding(1, 4, 2) lipgloss.NewStyle().Margin(2, 4, 3, 1) ``` +You can also customize the characters used for padding and margin fill: + +```go +s := lipgloss.NewStyle(). + Padding(1, 2). + PaddingChar('·'). + Margin(1, 2). + MarginChar('░') +``` + ## Aligning Text You can align paragraphs of text to the left, right, or center. @@ -221,7 +281,15 @@ lipgloss.NewStyle(). Border(lipgloss.DoubleBorder(), true, false, false, true) ``` -For more on borders see [the docs][docs]. +You can also pass multiple colors to a border for a gradient effect: + +```go +s := lipgloss.NewStyle(). + Border(lipgloss.RoundedBorder()). + BorderForegroundBlend(lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF")) +``` + +For more on borders see [the docs](https://pkg.go.dev/charm.land/lipgloss/v2#Border). ## Copying Styles @@ -233,12 +301,10 @@ style := lipgloss.NewStyle().Foreground(lipgloss.Color("219")) copiedStyle := style // this is a true copy wildStyle := style.Blink(true) // this is also true copy, with blink added - ``` -Since `Style` data structures contains only primitive types, assigning a style -to another effectively creates a new copy of the style without mutating the -original. +Since `Style` is a pure value type, assigning a style to another effectively +creates a new copy of the style without mutating the original. ## Inheritance @@ -269,7 +335,7 @@ var style = lipgloss.NewStyle(). UnsetBackground() // never mind ``` -When a rule is unset, it won't be inherited or copied. +When a rule is unset, it won’t be inherited or copied. ## Enforcing Rules @@ -302,50 +368,57 @@ style = style.TabWidth(0) // remove tabs entirely style = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact ``` +## Wrapping + +The `Wrap` function wraps text while preserving ANSI styles and hyperlinks +across line boundaries: + +```go +wrapped := lipgloss.Wrap(styledText, 40, " ") +``` + ## Rendering Generally, you just call the `Render(string...)` method on a `lipgloss.Style`: ```go style := lipgloss.NewStyle().Bold(true).SetString("Hello,") -fmt.Println(style.Render("kitty.")) // Hello, kitty. -fmt.Println(style.Render("puppy.")) // Hello, puppy. +lipgloss.Println(style.Render("kitty.")) // Hello, kitty. +lipgloss.Println(style.Render("puppy.")) // Hello, puppy. ``` But you could also use the Stringer interface: ```go var style = lipgloss.NewStyle().SetString("你好,猫咪。").Bold(true) -fmt.Println(style) // 你好,猫咪。 +lipgloss.Println(style) // 你好,猫咪。 ``` -### Custom Renderers +## Utilities -Custom renderers allow you to render to a specific outputs. This is -particularly important when you want to render to different outputs and -correctly detect the color profile and dark background status for each, such as -in a server-client situation. +In addition to pure styling, Lip Gloss also ships with some utilities to help +assemble your layouts. -```go -func myLittleHandler(sess ssh.Session) { - // Create a renderer for the client. - renderer := lipgloss.NewRenderer(sess) +### Compositing - // Create a new style on the renderer. - style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: "63", Dark: "228"}) +

xx

- // Render. The color profile and dark background state will be correctly detected. - io.WriteString(sess, style.Render("Heyyyyyyy")) -} -``` +Lip Gloss includes a powerful, cell-based compositor for rendering layered +content: -For an example on using a custom renderer over SSH with [Wish][wish] see the -[SSH example][ssh-example]. +```go +// Create some layers. +a := lipgloss.NewLayer(pickles).X(4).Y(2).Z(1) +b := lipgloss.NewLayer(bitterMelon).X(22).Y(1) +c := lipgloss.NewLayer(sriracha).X(11).Y(7) -## Utilities +// Composite 'em and render. +output := compositor.Compose(a, b, c).Render() +``` -In addition to pure styling, Lip Gloss also ships with some utilities to help -assemble your layouts. +For a more thorough example, see [the canvas +example](./examples/canvas/main.go). For reference, including how to detect +mouse clicks on layers, see [the docs][docs]. ### Joining Paragraphs @@ -383,9 +456,22 @@ height := lipgloss.Height(block) w, h := lipgloss.Size(block) ``` +### Blending Colors + +You can blend colors in one or two dimensions for gradient effects: + +```go +// 1-dimentinoal gradient +colors := lipgloss.Blend1D(10, lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF")) + +// 2-dimensional gradient with rotation +colors := lipgloss.Blend2D(80, 24, 45.0, color1, color2, color3) +``` + ### Placing Text in Whitespace -Sometimes you’ll simply want to place a block of text in whitespace. +Sometimes you’ll simply want to place a block of text in whitespace. This is +a lightweight alternative to compositing. ```go // Center a paragraph horizontally in a space 80 cells wide. The height of @@ -407,7 +493,7 @@ You can also style the whitespace. For details, see [the docs][docs]. Lip Gloss ships with a table rendering sub-package. ```go -import "github.com/charmbracelet/lipgloss/table" +import "charm.land/lipgloss/v2/table" ``` Define some rows of data. @@ -459,14 +545,11 @@ t.Row("English", "You look absolutely fabulous.", "How's it going?") Print the table. ```go -fmt.Println(t) +lipgloss.Println(t) ``` ![Table Example](https://github.com/charmbracelet/lipgloss/assets/42545625/6e4b70c4-f494-45da-a467-bdd27df30d5d) -> [!WARNING] -> Table `Rows` need to be declared before `Offset` otherwise it does nothing. - ### Table Borders There are helpers to generate tables in markdown or ASCII style: @@ -503,14 +586,14 @@ table.New().Border(lipgloss.ASCIIBorder()) +----------+--------------+-----------+ ``` -For more on tables see [the docs](https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc) and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table). +For more on tables see [the docs][docs] and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table). ## Rendering Lists Lip Gloss ships with a list rendering sub-package. ```go -import "github.com/charmbracelet/lipgloss/list" +import "charm.land/lipgloss/v2/list" ``` Define a new list. @@ -522,7 +605,7 @@ l := list.New("A", "B", "C") Print the list. ```go -fmt.Println(l) +lipgloss.Println(l) // • A // • B @@ -548,7 +631,7 @@ l := list.New( Print the list. ```go -fmt.Println(l) +lipgloss.Println(l) ```

@@ -564,7 +647,7 @@ itemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("212")).MarginRight(1 l := list.New( "Glossier", - "Claire’s Boutique", + "Claire's Boutique", "Nyx", "Mac", "Milk", @@ -617,7 +700,7 @@ for i := 0; i < repeat; i++ { Lip Gloss ships with a tree rendering sub-package. ```go -import "github.com/charmbracelet/lipgloss/tree" +import "charm.land/lipgloss/v2/tree" ``` Define a new tree. @@ -630,7 +713,7 @@ t := tree.Root("."). Print the tree. ```go -fmt.Println(t) +lipgloss.Println(t) // . // ├── A @@ -661,7 +744,7 @@ t := tree.Root("."). Print the tree. ```go -fmt.Println(t) +lipgloss.Println(t) ```

@@ -713,49 +796,159 @@ for i := 0; i < repeat; i++ { } ``` ---- +## Advanced Color Usage -## FAQ +One of the most powerful features of Lip Gloss is the ability to render +different colors at runtime depending on the user's terminal and environment, +allowing you to present the best possible user experience. -

- -Why are things misaligning? Why are borders at the wrong widths? - -

This is most likely due to your locale and encoding, particularly with -regard to Chinese, Japanese, and Korean (for example, zh_CN.UTF-8 -or ja_JP.UTF-8). The most direct way to fix this is to set -RUNEWIDTH_EASTASIAN=0 in your environment.

- -

For details see https://github.com/charmbracelet/lipgloss/issues/40.

-
+This section shows you how to do exactly that.
- -Why isn't Lip Gloss displaying colors? - -

Lip Gloss automatically degrades colors to the best available option in the -given terminal, and if output's not a TTY it will remove color output entirely. -This is common when running tests, CI, or when piping output elsewhere.

+Migrating from v1? -

If necessary, you can force a color profile in your tests with -SetColorProfile.

+The `compat` package provides `AdaptiveColor`, `CompleteColor`, and +`CompleteAdaptiveColor` for a quicker migration from v1. These work by +looking at `stdin` and `stdout` on a global basis: ```go -import ( - "github.com/charmbracelet/lipgloss" - "github.com/muesli/termenv" -) +import "charm.land/lipgloss/v2/compat" -lipgloss.SetColorProfile(termenv.TrueColor) +color := compat.AdaptiveColor{ + Light: lipgloss.Color("#f1f1f1"), + Dark: lipgloss.Color("#cccccc"), +} ``` -_Note:_ this option limits the flexibility of your application and can cause -ANSI escape codes to be output in cases where that might not be desired. Take -careful note of your use case and environment before choosing to force a color -profile. +Note that we don't recommend this for new code as it removes the purity from +Lip Gloss, computationally speaking, as it removes transparency around when +I/O happens, which could cause Lip Gloss to compete for resources (like stdin) +with other tools.
+### Adaptive Colors + +You can render different colors at runtime depending on whether the terminal +has a light or dark background: + +```go +hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout) +lightDark := lipgloss.LightDark(hasDarkBG) + +myColor := lightDark(lipgloss.Color("#D7FFAE"), lipgloss.Color("#D75FEE")) +``` + +#### With Bubble Tea + +In Bubble Tea, request the background color, listen for a +`BackgroundColorMsg`, and respond accordingly: + +```go +func (m model) Init() tea.Cmd { + // First, send a Cmd to request the terminal background color. + return tea.RequestBackgroundColor +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.BackgroundColorMsg: + // Great, we have the background color. Now we can set up our styles + // against the color. + m.styles = newStyles(msg.IsDark()) + return m, nil + } +} + +func newStyles(bgIsDark bool) styles { + // A little ternary function that will return the appropriate color + // based on the background color. + lightDark := lipgloss.LightDark(bgIsDark) + + return styles{ + myHotStyle: lipgloss.NewStyle().Foreground(lightDark( + lipgloss.Color("#f1f1f1"), + lipgloss.Color("#333333"), + )), + } +} +``` + +#### Standalone + +If you’re not using Bubble Tea you can perform the query manually: + +```go +// What's the background color? +hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stderr) + +// A helper function that will return the appropriate color based on the +// background. +lightDark := lipgloss.LightDark(hasDarkBG) + +// A couple colors with light and dark variants. +thisColor := lightDark(lipgloss.Color("#C5ADF9"), lipgloss.Color("#864EFF")) +thatColor := lightDark(lipgloss.Color("#37CD96"), lipgloss.Color("#22C78A")) + +a := lipgloss.NewStyle().Foreground(thisColor).Render("this") +b := lipgloss.NewStyle().Foreground(thatColor).Render("that") + +// Render the appropriate colors at runtime: +lipgloss.Fprintf(os.Stderr, "my fave colors are %s and %s", a, b) +``` + +### Complete Colors + +In some cases where you may want to specify exact values for each color profile +(ANSI 16, ANSI 156, and TrueColor). For these cases, use the `Complete` helper: + +```go +// You'll need the colorprofile package. +import "github.com/charmbracelet/colorprofile" + +// Get the color profile. +profile := colorprofile.Detect(os.Stdout, os.Environ()) + +// Create a function for rendering the appropriate color based on the profile. +var completeColor := lipgloss.Complete(profile) + +// Now we'll choose the appropriate color at runtime. +myColor := completeColor(ansiColor, ansi256Color, trueColor) +``` + +### Color Downsampling + +One of the best things about Lip Gloss is that it can automatically downsample +colors to the best available profile, stripping colors (and ANSI) entirely when +output is not a TTY. + +If you’re using Lip Gloss with Bubble Tea there’s nothing to do here: +downsampling is built into Bubble Tea v2. If you’re not using Bubble Tea, use +the Lip Gloss writer functions, which are a drop-in replacement for the `fmt` +package: + +```go +s := lipgloss.NewStyle() + .Foreground(lipgloss.Color("#EB4268")) + .Render("Hello!") + +// Downsample if needed and print to stdout. +lipgloss.Println(s) + +// Render to a variable. +downsampled := lipgloss.Sprint(s) + +// Print to stderr. +lipgloss.Fprint(os.Stderr, s) +``` + +The full set: `Print`, `Println`, `Printf`, `Fprint`, `Fprintln`, `Fprintf`, +`Sprint`, `Sprintln`, `Sprintf`. + +Need more control? Check out +[Colorprofile](https://github.com/charmbracelet/colorprofile), which Lip Gloss +uses under the hood. + ## What about [Bubble Tea][tea]? Lip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea @@ -765,16 +958,7 @@ instead of concerning yourself with low-level layout details. In simple terms, you can use Lip Gloss to help build your Bubble Tea views. -[tea]: https://github.com/charmbracelet/tea - -## Under the Hood - -Lip Gloss is built on the excellent [Termenv][termenv] and [Reflow][reflow] -libraries which deal with color and ANSI-aware text operations, respectively. -For many use cases Termenv and Reflow will be sufficient for your needs. - -[termenv]: https://github.com/muesli/termenv -[reflow]: https://github.com/muesli/reflow +[tea]: https://github.com/charmbracelet/bubbletea ## Rendering Markdown @@ -794,9 +978,8 @@ See [contributing][contribute]. We’d love to hear your thoughts on this project. Feel free to drop us a note! -- [Twitter](https://twitter.com/charmcli) -- [The Fediverse](https://mastodon.social/@charmcli) -- [Discord](https://charm.sh/chat) +- [Discord](https://charm.land/chat) +- [Matrix](https://charm.land/matrix) ## License @@ -804,12 +987,10 @@ We’d love to hear your thoughts on this project. Feel free to drop us a note! --- -Part of [Charm](https://charm.sh). +Part of [Charm](https://charm.land). -The Charm logo +The Charm logo Charm热爱开源 • Charm loves open source -[docs]: https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc -[wish]: https://github.com/charmbracelet/wish -[ssh-example]: examples/ssh +[docs]: https://pkg.go.dev/charm.land/lipgloss/v2?tab=doc diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml b/tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml similarity index 72% rename from tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml rename to tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml index 0b4a7711a..84fcf6c66 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml +++ b/tools/vendor/charm.land/lipgloss/v2/Taskfile.yaml @@ -1,6 +1,6 @@ # https://taskfile.dev -version: '3' +version: "3" tasks: lint: @@ -17,3 +17,8 @@ tasks: desc: Run table tests cmds: - go test ./table {{.CLI_ARGS}} + + test:tree: + desc: Run tree tests + cmds: + - go test ./tree {{.CLI_ARGS}} diff --git a/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md b/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md new file mode 100644 index 000000000..8f123f19d --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md @@ -0,0 +1,504 @@ +# Lip Gloss v2 Upgrade Guide + +This guide covers migrating from Lip Gloss v1 (`github.com/charmbracelet/lipgloss`) +to Lip Gloss v2 (`charm.land/lipgloss/v2`). It is written for both humans and +LLMs performing automated migrations. + +--- + +## Table of Contents + +1. [Quick Start](#quick-start) +2. [Module Path](#module-path) +3. [Color System](#color-system) +4. [Renderer Removal](#renderer-removal) +5. [Printing and Color Downsampling](#printing-and-color-downsampling) +6. [Background Detection and Adaptive Colors](#background-detection-and-adaptive-colors) +7. [Whitespace Options](#whitespace-options) +8. [Underline](#underline) +9. [Style API Changes](#style-api-changes) +10. [Tree Subpackage](#tree-subpackage) +11. [Removed APIs](#removed-apis) +12. [Quick Reference Table](#quick-reference-table) + +--- + +## Quick Start + +For the fastest possible upgrade, do these two things: + +### 1. Use the `compat` package for adaptive/complete colors + +```go +import "charm.land/lipgloss/v2/compat" + +// v1 +color := lipgloss.AdaptiveColor{Light: "#f1f1f1", Dark: "#cccccc"} + +// v2 +color := compat.AdaptiveColor{Light: lipgloss.Color("#f1f1f1"), Dark: lipgloss.Color("#cccccc")} +``` + +The `compat` package reads `stdin`/`stdout` globally, just like v1. To +customize: + +```go +import ( + "charm.land/lipgloss/v2/compat" + "github.com/charmbracelet/colorprofile" +) + +func init() { + compat.HasDarkBackground = lipgloss.HasDarkBackground(os.Stdin, os.Stderr) + compat.Profile = colorprofile.Detect(os.Stderr, os.Environ()) +} +``` + +### 2. Use Lip Gloss writers for output + +```go +// v1 +fmt.Println(s) + +// v2 +lipgloss.Println(s) +``` + +This ensures colors are automatically downsampled. If you're using Bubble Tea +v2, this step is unnecessary — Bubble Tea handles it for you. + +**That's the quick path.** Read on for the full migration details. + +--- + +## Module Path + +The import path has changed. + +```go +// v1 +import "github.com/charmbracelet/lipgloss" + +// v2 +import "charm.land/lipgloss/v2" +``` + +**Install:** + +```bash +go get charm.land/lipgloss/v2 +``` + +All subpackages follow the same pattern: + +```go +// v1 +import "github.com/charmbracelet/lipgloss/table" +import "github.com/charmbracelet/lipgloss/tree" +import "github.com/charmbracelet/lipgloss/list" + +// v2 +import "charm.land/lipgloss/v2/table" +import "charm.land/lipgloss/v2/tree" +import "charm.land/lipgloss/v2/list" +``` + +**Search-and-replace pattern:** + +``` +github.com/charmbracelet/lipgloss → charm.land/lipgloss/v2 +``` + +--- + +## Color System + +This is the most significant API change. + +### `Color` is now a function, not a type + +```go +// v1 — Color is a string type +var c lipgloss.Color = "21" +var c lipgloss.Color = "#ff00ff" + +// v2 — Color is a function returning color.Color +var c color.Color = lipgloss.Color("21") +var c color.Color = lipgloss.Color("#ff00ff") +``` + +The return type is `image/color.Color` (from the standard library). + +### `TerminalColor` interface is removed + +All methods that accepted `lipgloss.TerminalColor` now accept +`image/color.Color`: + +```go +// v1 +func (s Style) Foreground(c TerminalColor) Style +func (s Style) Background(c TerminalColor) Style +func (s Style) BorderForeground(c ...TerminalColor) Style + +// v2 +func (s Style) Foreground(c color.Color) Style +func (s Style) Background(c color.Color) Style +func (s Style) BorderForeground(c ...color.Color) Style +``` + +**Migration:** Replace every `lipgloss.TerminalColor` with `color.Color` and +add `import "image/color"`. + +### `ANSIColor` is now an alias + +```go +// v1 — custom uint type +type ANSIColor uint + +// v2 — alias for ansi.IndexedColor +type ANSIColor = ansi.IndexedColor +``` + +v2 also exports named constants for the 16 basic ANSI colors: + +```go +lipgloss.Black, lipgloss.Red, lipgloss.Green, lipgloss.Yellow, +lipgloss.Blue, lipgloss.Magenta, lipgloss.Cyan, lipgloss.White, +lipgloss.BrightBlack, lipgloss.BrightRed, lipgloss.BrightGreen, +lipgloss.BrightYellow, lipgloss.BrightBlue, lipgloss.BrightMagenta, +lipgloss.BrightCyan, lipgloss.BrightWhite +``` + +### `AdaptiveColor`, `CompleteColor`, `CompleteAdaptiveColor` + +These types have been moved out of the root package. Use the `compat` package +for a drop-in replacement, or use the new `LightDark` and `Complete` helpers +for explicit control: + +```go +// v1 +color := lipgloss.AdaptiveColor{Light: "#0000ff", Dark: "#000099"} + +// v2 — using compat (quick path) +color := compat.AdaptiveColor{ + Light: lipgloss.Color("#0000ff"), + Dark: lipgloss.Color("#000099"), +} + +// v2 — using LightDark (recommended) +hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout) +lightDark := lipgloss.LightDark(hasDark) +color := lightDark(lipgloss.Color("#0000ff"), lipgloss.Color("#000099")) +``` + +```go +// v1 +color := lipgloss.CompleteColor{TrueColor: "#ff00ff", ANSI256: "200", ANSI: "5"} + +// v2 — using compat +color := compat.CompleteColor{ + TrueColor: lipgloss.Color("#ff00ff"), + ANSI256: lipgloss.Color("200"), + ANSI: lipgloss.Color("5"), +} + +// v2 — using Complete (recommended) +profile := colorprofile.Detect(os.Stdout, os.Environ()) +complete := lipgloss.Complete(profile) +color := complete(lipgloss.Color("5"), lipgloss.Color("200"), lipgloss.Color("#ff00ff")) +``` + +Note that `compat.AdaptiveColor` and friends take `color.Color` values for +their fields, not strings. + +--- + +## Renderer Removal + +The `Renderer` type and all associated functions are removed. In v1, every +`Style` carried a `*Renderer` pointer and the package maintained a global +default renderer. + +```go +// v1 — these no longer exist +lipgloss.DefaultRenderer() +lipgloss.SetDefaultRenderer(r) +lipgloss.NewRenderer(w, opts...) +lipgloss.ColorProfile() +lipgloss.SetColorProfile(p) +renderer.NewStyle() +``` + +**In v2, `Style` is a plain value type.** There is no renderer. Color +downsampling is handled at the output layer (see next section). + +**Migration:** + +- Replace `lipgloss.DefaultRenderer().NewStyle()` with `lipgloss.NewStyle()`. +- Replace `renderer.NewStyle()` with `lipgloss.NewStyle()`. +- Remove any `*Renderer` fields from your types. +- Remove calls to `SetColorProfile` — use `colorprofile.Detect` at the output + layer instead. + +--- + +## Printing and Color Downsampling + +In v1, color downsampling happened inside `Style.Render()` via the renderer. In +v2, `Render()` always emits full-fidelity ANSI. Downsampling happens when you +print. + +### Standalone Usage + +Use the Lip Gloss writer functions: + +```go +s := someStyle.Render("Hello!") + +// Print to stdout with automatic downsampling +lipgloss.Println(s) + +// Print to stderr +lipgloss.Fprintln(os.Stderr, s) + +// Render to a string (downsampled for stdout's profile) +str := lipgloss.Sprint(s) +``` + +The default writer targets `stdout`. To customize: + +```go +lipgloss.Writer = colorprofile.NewWriter(os.Stderr, os.Environ()) +``` + +### With Bubble Tea + +No changes needed. Bubble Tea v2 handles downsampling internally. + +--- + +## Background Detection and Adaptive Colors + +### Standalone + +v1 detected the background color automatically via the global renderer. v2 +requires explicit queries: + +```go +// v1 +hasDark := lipgloss.HasDarkBackground() + +// v2 — specify the input and output +hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout) +``` + +Then use `LightDark` to pick colors: + +```go +lightDark := lipgloss.LightDark(hasDark) +fg := lightDark(lipgloss.Color("#333333"), lipgloss.Color("#f1f1f1")) + +s := lipgloss.NewStyle().Foreground(fg) +``` + +### With Bubble Tea + +Request the background color in `Init` and listen for the response: + +```go +func (m model) Init() tea.Cmd { + return tea.RequestBackgroundColor +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.BackgroundColorMsg: + m.styles = newStyles(msg.IsDark()) + } + // ... +} + +func newStyles(bgIsDark bool) styles { + lightDark := lipgloss.LightDark(bgIsDark) + return styles{ + title: lipgloss.NewStyle().Foreground(lightDark( + lipgloss.Color("#333333"), + lipgloss.Color("#f1f1f1"), + )), + } +} +``` + +--- + +## Whitespace Options + +The separate foreground/background whitespace options have been replaced by a +single style option: + +```go +// v1 +lipgloss.Place(width, height, hPos, vPos, str, + lipgloss.WithWhitespaceForeground(lipgloss.Color("#333")), + lipgloss.WithWhitespaceBackground(lipgloss.Color("#000")), +) + +// v2 +lipgloss.Place(width, height, hPos, vPos, str, + lipgloss.WithWhitespaceStyle(lipgloss.NewStyle(). + Foreground(lipgloss.Color("#333")). + Background(lipgloss.Color("#000")), + ), +) +``` + +--- + +## Underline + +`Underline(bool)` still works for basic on/off. v2 adds fine-grained control: + +```go +// v1 +s := lipgloss.NewStyle().Underline(true) + +// v2 — still works +s := lipgloss.NewStyle().Underline(true) + +// v2 — new: specific styles +s := lipgloss.NewStyle().UnderlineStyle(lipgloss.UnderlineCurly) + +// v2 — new: colored underlines +s := lipgloss.NewStyle(). + UnderlineStyle(lipgloss.UnderlineSingle). + UnderlineColor(lipgloss.Color("#FF0000")) +``` + +Internally, `Underline(true)` is equivalent to `UnderlineStyle(UnderlineSingle)` +and `Underline(false)` is equivalent to `UnderlineStyle(UnderlineNone)`. + +--- + +## Style API Changes + +### `NewStyle()` is no longer tied to a Renderer + +```go +// v1 +s := lipgloss.NewStyle() // uses global renderer +s := renderer.NewStyle() // uses specific renderer + +// v2 +s := lipgloss.NewStyle() // pure value, no renderer +``` + +### Color getters return `color.Color` + +```go +// v1 +fg := s.GetForeground() // returns TerminalColor + +// v2 +fg := s.GetForeground() // returns color.Color +``` + +### New style methods + +| Method | Description | +|---|---| +| `UnderlineStyle(Underline)` | Set underline style (single, double, curly, etc.) | +| `UnderlineColor(color.Color)` | Set underline color | +| `PaddingChar(rune)` | Set the character used for padding fill | +| `MarginChar(rune)` | Set the character used for margin fill | +| `Hyperlink(link, params...)` | Set a clickable hyperlink | +| `BorderForegroundBlend(...color.Color)` | Apply gradient colors to borders | +| `BorderForegroundBlendOffset(int)` | Set the offset for border gradient | + +Each has a corresponding `Get*`, `Unset*`, and where applicable `Get*` +accessor. + +--- + +## Tree Subpackage + +The import path changes and there are new styling options: + +```go +// v1 +import "github.com/charmbracelet/lipgloss/tree" + +// v2 +import "charm.land/lipgloss/v2/tree" +``` + +New methods: + +- `IndenterStyle(lipgloss.Style)` — set a static style for tree indentation. +- `IndenterStyleFunc(func(Children, int) lipgloss.Style)` — conditionally style + indentation. +- `Width(int)` — set tree width for padding. + +--- + +## Removed APIs + +The following types and functions no longer exist in v2. This table shows each +removed symbol and its replacement. + +| v1 Symbol | v2 Replacement | +|---|---| +| `type Renderer` | Removed entirely | +| `DefaultRenderer()` | Not needed | +| `SetDefaultRenderer(r)` | Not needed | +| `NewRenderer(w, opts...)` | Not needed | +| `ColorProfile()` | `colorprofile.Detect(w, env)` | +| `SetColorProfile(p)` | Set `lipgloss.Writer.Profile` | +| `HasDarkBackground()` (no args) | `lipgloss.HasDarkBackground(in, out)` | +| `SetHasDarkBackground(b)` | Not needed — pass bool to `LightDark` | +| `type TerminalColor` | `image/color.Color` | +| `type Color string` | `func Color(string) color.Color` | +| `type ANSIColor uint` | `type ANSIColor = ansi.IndexedColor` | +| `type AdaptiveColor` | `compat.AdaptiveColor` or `LightDark` | +| `type CompleteColor` | `compat.CompleteColor` or `Complete` | +| `type CompleteAdaptiveColor` | `compat.CompleteAdaptiveColor` | +| `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(s)` | +| `WithWhitespaceBackground(c)` | `WithWhitespaceStyle(s)` | +| `renderer.NewStyle()` | `lipgloss.NewStyle()` | + +--- + +## Quick Reference Table + +A side-by-side summary for common patterns: + +| Task | v1 | v2 | +|---|---|---| +| Import | `"github.com/charmbracelet/lipgloss"` | `"charm.land/lipgloss/v2"` | +| Create style | `lipgloss.NewStyle()` | `lipgloss.NewStyle()` | +| Hex color | `lipgloss.Color("#ff00ff")` | `lipgloss.Color("#ff00ff")` | +| ANSI color | `lipgloss.Color("5")` | `lipgloss.Color("5")` or `lipgloss.Magenta` | +| Adaptive color | `lipgloss.AdaptiveColor{Light: "#fff", Dark: "#000"}` | `compat.AdaptiveColor{Light: lipgloss.Color("#fff"), Dark: lipgloss.Color("#000")}` | +| Set foreground | `s.Foreground(lipgloss.Color("5"))` | `s.Foreground(lipgloss.Color("5"))` | +| Print with downsampling | `fmt.Println(s.Render("hi"))` | `lipgloss.Println(s.Render("hi"))` | +| Detect dark bg | `lipgloss.HasDarkBackground()` | `lipgloss.HasDarkBackground(os.Stdin, os.Stdout)` | +| Light/dark color | `lipgloss.AdaptiveColor{...}` | `lipgloss.LightDark(isDark)(light, dark)` | +| Whitespace styling | `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(lipgloss.NewStyle().Foreground(c))` | +| Underline | `s.Underline(true)` | `s.Underline(true)` or `s.UnderlineStyle(lipgloss.UnderlineCurly)` | + +--- + +## Feedback + +Questions, issues, or feedback: + +- [Discord](https://charm.land/discord) +- [Matrix](https://charm.land/matrix) +- [Email](mailto:vt100@charm.land) + +--- + +Part of [Charm](https://charm.land). + +The Charm logo + +Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/align.go b/tools/vendor/charm.land/lipgloss/v2/align.go similarity index 89% rename from tools/vendor/github.com/charmbracelet/lipgloss/align.go rename to tools/vendor/charm.land/lipgloss/v2/align.go index ce654b232..d196213b7 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/align.go +++ b/tools/vendor/charm.land/lipgloss/v2/align.go @@ -4,13 +4,12 @@ import ( "strings" "github.com/charmbracelet/x/ansi" - "github.com/muesli/termenv" ) // Perform text alignment. If the string is multi-lined, we also make all lines -// the same width by padding them with spaces. If a termenv style is passed, -// use that to style the spaces added. -func alignTextHorizontal(str string, pos Position, width int, style *termenv.Style) string { +// the same width by padding them with spaces. If a style is passed, use that +// to style the spaces added. +func alignTextHorizontal(str string, pos Position, width int, style *ansi.Style) string { lines, widestLine := getLines(str) var b strings.Builder @@ -21,7 +20,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty shortAmount += max(0, width-(shortAmount+lineWidth)) // difference from the total width, if set if shortAmount > 0 { - switch pos { //nolint:exhaustive + switch pos { case Right: s := strings.Repeat(" ", shortAmount) if style != nil { @@ -59,7 +58,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty return b.String() } -func alignTextVertical(str string, pos Position, height int, _ *termenv.Style) string { +func alignTextVertical(str string, pos Position, height int, _ *ansi.Style) string { strHeight := strings.Count(str, "\n") + 1 if height < strHeight { return str diff --git a/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go b/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go new file mode 100644 index 000000000..b4fca7d19 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/ansi_unix.go @@ -0,0 +1,8 @@ +//go:build !windows + +package lipgloss + +import "os" + +// EnableLegacyWindowsANSI is only needed on Windows. +func EnableLegacyWindowsANSI(*os.File) {} diff --git a/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go b/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go new file mode 100644 index 000000000..8a1ef00eb --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/ansi_windows.go @@ -0,0 +1,30 @@ +//go:build windows + +package lipgloss + +import ( + "os" + + "golang.org/x/sys/windows" +) + +// EnableLegacyWindowsANSI enables support for ANSI color sequences in the +// Windows default console (cmd.exe and the PowerShell application). Note that +// this only works with Windows 10 and greater. Also note that Windows Terminal +// supports colors by default. +func EnableLegacyWindowsANSI(f *os.File) { + var mode uint32 + handle := windows.Handle(f.Fd()) + err := windows.GetConsoleMode(handle, &mode) + if err != nil { + return + } + + // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences + if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING { + vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING + if err := windows.SetConsoleMode(handle, vtpmode); err != nil { + return + } + } +} diff --git a/tools/vendor/charm.land/lipgloss/v2/blending.go b/tools/vendor/charm.land/lipgloss/v2/blending.go new file mode 100644 index 000000000..82830f3e4 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/blending.go @@ -0,0 +1,196 @@ +package lipgloss + +import ( + "image/color" + "math" + "slices" + + "github.com/lucasb-eyer/go-colorful" +) + +// Blend1D blends a series of colors together in one linear dimension using multiple +// stops, into the provided number of steps. Uses the "CIE L*, a*, b*" (CIELAB) color-space. +// +// Note that if any of the provided colors are completely transparent, we will +// assume that the alpha value was lost in conversion from RGB -> RGBA, and we +// will set the alpha to opaque, as it's not possible to blend something completely +// transparent. +func Blend1D(steps int, stops ...color.Color) []color.Color { + if steps < 0 { + steps = 0 + } + + if steps <= len(stops) { + return stops[:steps] + } + + // Ensure they didn't provide any nil colors. + stops = slices.DeleteFunc(stops, func(c color.Color) bool { + return c == nil + }) + + if len(stops) == 0 { + return nil // We can't safely fallback. + } + + // If they only provided one valid color (or some nil colors), we will just return + // an array of that color, for the amount of steps they requested. + if len(stops) == 1 { + singleColor := stops[0] + result := make([]color.Color, steps) + for i := range result { + result[i] = singleColor + } + return result + } + + blended := make([]color.Color, steps) + + // Convert stops to colorful.Color once + cstops := make([]colorful.Color, len(stops)) + for i, k := range stops { + cstops[i], _ = colorful.MakeColor(ensureNotTransparent(k)) + } + + numSegments := len(cstops) - 1 + defaultSize := steps / numSegments + remainingSteps := steps % numSegments + + resultIndex := 0 + for i := range numSegments { + from := cstops[i] + to := cstops[i+1] + + // Calculate segment size. + segmentSize := defaultSize + if i < remainingSteps { + segmentSize++ + } + + divisor := float64(segmentSize - 1) + + // Generate colors for this segment. + for j := 0; j < segmentSize; j++ { + var blendingFactor float64 + if segmentSize > 1 { + blendingFactor = float64(j) / divisor + } + blended[resultIndex] = from.BlendLab(to, blendingFactor).Clamped() + resultIndex++ + } + } + + return blended +} + +// Blend2D blends a series of colors together in two linear dimensions using +// multiple stops, into the provided width/height. Uses the "CIE L*, a*, b*" (CIELAB) +// color-space. The angle parameter controls the rotation of the gradient (0-360°), +// where 0° is left-to-right, 45° is bottom-left to top-right (diagonal). The function +// returns colors in a 1D row-major order ([row1, row2, row3, ...]). +// +// Example of how to iterate over the result: +// +// gradient := colors.Blend2D(width, height, 180, color1, color2, color3, ...) +// gradientContent := strings.Builder{} +// for y := range height { +// for x := range width { +// index := y*width + x +// gradientContent.WriteString( +// lipgloss.NewStyle(). +// Background(gradient[index]). +// Render(" "), +// ) +// } +// if y < height-1 { // End of row. +// gradientContent.WriteString("\n") +// } +// } +// +// Note that if any of the provided colors are completely transparent, we will +// assume that the alpha value was lost in conversion from RGB -> RGBA, and we +// will set the alpha to opaque, as it's not possible to blend something completely +// transparent. +func Blend2D(width, height int, angle float64, stops ...color.Color) []color.Color { + if width < 1 { + width = 1 + } + if height < 1 { + height = 1 + } + + // Normalize angle to 0-360. + angle = math.Mod(angle, 360) + if angle < 0 { + angle += 360 + } + + // Ensure they didn't provide any nil colors. + stops = slices.DeleteFunc(stops, func(c color.Color) bool { + return c == nil + }) + + if len(stops) == 0 { + return nil // We can't safely fallback. + } + + // If they only provided one valid color (or some nil colors), we will just return + // an array of that color, for the amount of pixels they requested. + if len(stops) == 1 { + singleColor := stops[0] + result := make([]color.Color, width*height) + for i := range result { + result[i] = singleColor + } + return result + } + + // For 2D blending, we'll create a gradient along the diagonal and then sample + // from it based on the angle. We'll use the maximum dimension to ensure we have + // enough resolution for the gradient. + diagonalGradient := Blend1D(max(width, height), stops...) + + result := make([]color.Color, width*height) + + // Calculate center point for rotation. + centerX := float64(width-1) / 2.0 + centerY := float64(height-1) / 2.0 + + angleRad := angle * math.Pi / 180.0 // -> radians. + + // Pre-calculate sin and cos. + cosAngle := math.Cos(angleRad) + sinAngle := math.Sin(angleRad) + + // Calculate diagonal length for proper gradient mapping. + diagonalLength := math.Sqrt(float64(width*width + height*height)) + + // Pre-calculate gradient length for index calculation. + gradientLen := float64(len(diagonalGradient) - 1) + + for y := range height { + // Calculate the distance from center along the gradient direction. + dy := float64(y) - centerY + + for x := 0; x < width; x++ { + // Calculate the distance from center along the gradient direction. + dx := float64(x) - centerX + + rotX := dx*cosAngle - dy*sinAngle // Rotate the point by the angle. + + // Map the rotated position to the gradient. Normalize to 0-1 range based on + // the diagonal length. + gradientPos := clamp((rotX+diagonalLength/2.0)/diagonalLength, 0, 1) + + // Calculate the index in the gradient. + gradientIndex := int(gradientPos * gradientLen) + if gradientIndex >= len(diagonalGradient) { + gradientIndex = len(diagonalGradient) - 1 + } + + result[y*width+x] = diagonalGradient[gradientIndex] // -> row-major order. + } + } + + return result +} diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/borders.go b/tools/vendor/charm.land/lipgloss/v2/borders.go similarity index 73% rename from tools/vendor/github.com/charmbracelet/lipgloss/borders.go rename to tools/vendor/charm.land/lipgloss/v2/borders.go index b36f87438..7f12360f6 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/borders.go +++ b/tools/vendor/charm.land/lipgloss/v2/borders.go @@ -1,10 +1,13 @@ package lipgloss import ( + "image/color" + "slices" "strings" + "unicode/utf8" "github.com/charmbracelet/x/ansi" - "github.com/muesli/termenv" + "github.com/clipperhouse/displaywidth" "github.com/rivo/uniseg" ) @@ -56,10 +59,7 @@ func (b Border) GetLeftSize() int { func getBorderEdgeWidth(borderParts ...string) (maxWidth int) { for _, piece := range borderParts { - w := maxRuneWidth(piece) - if w > maxWidth { - maxWidth = w - } + maxWidth = max(maxWidth, maxRuneWidth(piece)) } return maxWidth } @@ -278,6 +278,52 @@ func ASCIIBorder() Border { return asciiBorder } +type borderBlend struct { + topGradient []color.Color + rightGradient []color.Color + bottomGradient []color.Color + leftGradient []color.Color +} + +func (s Style) borderBlend(width, height int, colors ...color.Color) *borderBlend { + gradient := Blend1D( + (height+width+2)*2, + colors..., + ) + + // Rotate array forward or reverse based on the offset if provided. + if r := -s.getAsInt(borderForegroundBlendOffsetKey); r != 0 { + n := len(gradient) + r %= n + if r < 0 { + r += n + } + slices.Reverse(gradient[:r]) + slices.Reverse(gradient[r:]) + slices.Reverse(gradient) + } + + offset := 0 + getFromOffset := func(size int) (s []color.Color) { + s = gradient[offset : offset+size] + offset += size + return s + } + + blend := &borderBlend{ + topGradient: getFromOffset(width + 2), + rightGradient: getFromOffset(height), + bottomGradient: getFromOffset(width + 2), + leftGradient: getFromOffset(height), + } + + // bottom and left gradients are reversed because they are drawn in reverse order. + slices.Reverse(blend.bottomGradient) + slices.Reverse(blend.leftGradient) + + return blend +} + func (s Style) applyBorder(str string) string { var ( border = s.getBorderStyle() @@ -285,21 +331,11 @@ func (s Style) applyBorder(str string) string { hasRight = s.getAsBool(borderRightKey, false) hasBottom = s.getAsBool(borderBottomKey, false) hasLeft = s.getAsBool(borderLeftKey, false) - - topFG = s.getAsColor(borderTopForegroundKey) - rightFG = s.getAsColor(borderRightForegroundKey) - bottomFG = s.getAsColor(borderBottomForegroundKey) - leftFG = s.getAsColor(borderLeftForegroundKey) - - topBG = s.getAsColor(borderTopBackgroundKey) - rightBG = s.getAsColor(borderRightBackgroundKey) - bottomBG = s.getAsColor(borderBottomBackgroundKey) - leftBG = s.getAsColor(borderLeftBackgroundKey) ) // If a border is set and no sides have been specifically turned on or off // render borders on all sides. - if s.implicitBorders() { + if s.isBorderStyleSetWithoutSides() { hasTop = true hasRight = true hasBottom = true @@ -320,8 +356,11 @@ func (s Style) applyBorder(str string) string { width += maxRuneWidth(border.Left) } - if hasRight && border.Right == "" { - border.Right = " " + if hasRight { + if border.Right == "" { + border.Right = " " + } + width += maxRuneWidth(border.Right) } // If corners should be rendered but are set with the empty string, fill them @@ -370,13 +409,35 @@ func (s Style) applyBorder(str string) string { border.BottomRight = getFirstRuneAsString(border.BottomRight) border.BottomLeft = getFirstRuneAsString(border.BottomLeft) + var topFG, rightFG, bottomFG, leftFG color.Color + var ( + blendFG = s.getAsColors(borderForegroundBlendKey) + topBG = s.getAsColor(borderTopBackgroundKey) + rightBG = s.getAsColor(borderRightBackgroundKey) + bottomBG = s.getAsColor(borderBottomBackgroundKey) + leftBG = s.getAsColor(borderLeftBackgroundKey) + ) + + var blend *borderBlend + if len(blendFG) > 0 { + blend = s.borderBlend(width, len(lines), blendFG...) + } else { + topFG = s.getAsColor(borderTopForegroundKey) + rightFG = s.getAsColor(borderRightForegroundKey) + bottomFG = s.getAsColor(borderBottomForegroundKey) + leftFG = s.getAsColor(borderLeftForegroundKey) + } + var out strings.Builder // Render top if hasTop { top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width) - top = s.styleBorder(top, topFG, topBG) - out.WriteString(top) + if blend != nil { + out.WriteString(s.styleBorderBlend(top, blend.topGradient, topBG)) + } else { + out.WriteString(s.styleBorder(top, topFG, topBG)) + } out.WriteRune('\n') } @@ -387,23 +448,32 @@ func (s Style) applyBorder(str string) string { rightIndex := 0 // Render sides + var r string for i, l := range lines { if hasLeft { - r := string(leftRunes[leftIndex]) + r = string(leftRunes[leftIndex]) leftIndex++ if leftIndex >= len(leftRunes) { leftIndex = 0 } - out.WriteString(s.styleBorder(r, leftFG, leftBG)) + if blend != nil { + out.WriteString(s.styleBorder(r, blend.leftGradient[i], leftBG)) + } else { + out.WriteString(s.styleBorder(r, leftFG, leftBG)) + } } out.WriteString(l) if hasRight { - r := string(rightRunes[rightIndex]) + r = string(rightRunes[rightIndex]) rightIndex++ if rightIndex >= len(rightRunes) { rightIndex = 0 } - out.WriteString(s.styleBorder(r, rightFG, rightBG)) + if blend != nil { + out.WriteString(s.styleBorder(r, blend.rightGradient[i], rightBG)) + } else { + out.WriteString(s.styleBorder(r, rightFG, rightBG)) + } } if i < len(lines)-1 { out.WriteRune('\n') @@ -413,9 +483,12 @@ func (s Style) applyBorder(str string) string { // Render bottom if hasBottom { bottom := renderHorizontalEdge(border.BottomLeft, border.Bottom, border.BottomRight, width) - bottom = s.styleBorder(bottom, bottomFG, bottomBG) out.WriteRune('\n') - out.WriteString(bottom) + if blend != nil { + out.WriteString(s.styleBorderBlend(bottom, blend.bottomGradient, bottomBG)) + } else { + out.WriteString(s.styleBorder(bottom, bottomFG, bottomBG)) + } } return out.String() @@ -435,49 +508,73 @@ func renderHorizontalEdge(left, middle, right string, width int) string { out := strings.Builder{} out.WriteString(left) - for i := leftWidth + rightWidth; i < width+rightWidth; { - out.WriteRune(runes[j]) + + for i := 0; i < width-leftWidth-rightWidth; { + r := runes[j] + out.WriteRune(r) + i += ansi.StringWidth(string(r)) j++ if j >= len(runes) { j = 0 } - i += ansi.StringWidth(string(runes[j])) } - out.WriteString(right) + out.WriteString(right) return out.String() } -// Apply foreground and background styling to a border. -func (s Style) styleBorder(border string, fg, bg TerminalColor) string { +// styleBorder applies foreground and background styling to a border. +func (s Style) styleBorder(border string, fg, bg color.Color) string { if fg == noColor && bg == noColor { return border } - - style := termenv.Style{} - + var style ansi.Style if fg != noColor { - style = style.Foreground(fg.color(s.r)) + style = style.ForegroundColor(fg) } if bg != noColor { - style = style.Background(bg.color(s.r)) + style = style.BackgroundColor(bg) } - return style.Styled(border) } +// styleBorderBlend applies foreground and background styling to a border, using blending. +func (s Style) styleBorderBlend(border string, fg []color.Color, bg color.Color) string { + var out strings.Builder + var style ansi.Style + var i int + + gr := uniseg.NewGraphemes(border) + for gr.Next() { + style = style[:0] + if fg[i] != noColor { + style = style.ForegroundColor(fg[i]) + } + if bg != noColor { + style = style.BackgroundColor(bg) + } + _, _ = out.WriteString(style.String()) + _, _ = out.Write(gr.Bytes()) + i++ + } + _, _ = out.WriteString(ansi.ResetStyle) + return out.String() +} + func maxRuneWidth(str string) int { + switch len(str) { + case 0: + return 0 + case 1: + return displaywidth.String(str) + } + var width int - state := -1 - for len(str) > 0 { - var w int - _, str, w, state = uniseg.FirstGraphemeClusterInString(str, state) - if w > width { - width = w - } + g := displaywidth.StringGraphemes(str) + for g.Next() { + width = max(width, g.Width()) } - return width } @@ -485,6 +582,6 @@ func getFirstRuneAsString(str string) string { if str == "" { return str } - r := []rune(str) - return string(r[0]) + _, size := utf8.DecodeRuneInString(str) + return str[:size] } diff --git a/tools/vendor/charm.land/lipgloss/v2/canvas.go b/tools/vendor/charm.land/lipgloss/v2/canvas.go new file mode 100644 index 000000000..396defb8b --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/canvas.go @@ -0,0 +1,88 @@ +package lipgloss + +import ( + uv "github.com/charmbracelet/ultraviolet" + "github.com/charmbracelet/x/ansi" +) + +// Canvas is a cell-buffer that can be used to compose and draw [uv.Drawable]s +// like [Layer]s. +// +// Composed drawables are drawn onto the canvas in the order they were +// composed, meaning later drawables will appear "on top" of earlier ones. +// +// A canvas can read, modify, and render its cell contents. +// +// It implements [uv.Screen] and [uv.Drawable]. +type Canvas struct { + scr uv.ScreenBuffer +} + +var _ uv.Screen = (*Canvas)(nil) + +// NewCanvas creates a new [Canvas] with the given size. +func NewCanvas(width, height int) *Canvas { + c := new(Canvas) + c.scr = uv.NewScreenBuffer(width, height) + c.scr.Method = ansi.GraphemeWidth + return c +} + +// Resize resizes the canvas to the given width and height. +func (c *Canvas) Resize(width, height int) { + c.scr.Resize(width, height) +} + +// Clear clears the canvas. +func (c *Canvas) Clear() { + c.scr.Clear() +} + +// Bounds implements [uv.Screen]. +func (c *Canvas) Bounds() uv.Rectangle { + return c.scr.Bounds() +} + +// Width returns the width of the canvas. +func (c *Canvas) Width() int { + return c.scr.Width() +} + +// Height returns the height of the canvas. +func (c *Canvas) Height() int { + return c.scr.Height() +} + +// CellAt implements [uv.Screen]. +func (c *Canvas) CellAt(x int, y int) *uv.Cell { + return c.scr.CellAt(x, y) +} + +// SetCell implements [uv.Screen]. +func (c *Canvas) SetCell(x int, y int, cell *uv.Cell) { + c.scr.SetCell(x, y, cell) +} + +// WidthMethod implements [uv.Screen]. +func (c *Canvas) WidthMethod() uv.WidthMethod { + return c.scr.WidthMethod() +} + +// Compose composes a [Layer] or any [uv.Drawable] onto the [Canvas]. +func (c *Canvas) Compose(drawer uv.Drawable) *Canvas { + drawer.Draw(c, c.Bounds()) + return c +} + +// Draw draws the [Canvas] onto the given [uv.Screen] within the specified +// area. +// +// It implements [uv.Drawable]. +func (c *Canvas) Draw(scr uv.Screen, area uv.Rectangle) { + c.scr.Draw(scr, area) +} + +// Render renders the canvas into a styled string. +func (c *Canvas) Render() string { + return c.scr.Render() +} diff --git a/tools/vendor/charm.land/lipgloss/v2/color.go b/tools/vendor/charm.land/lipgloss/v2/color.go new file mode 100644 index 000000000..7443dc10b --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/color.go @@ -0,0 +1,359 @@ +package lipgloss + +import ( + "cmp" + "errors" + "image/color" + "strconv" + "strings" + + "github.com/charmbracelet/colorprofile" + "github.com/charmbracelet/x/ansi" + "github.com/lucasb-eyer/go-colorful" +) + +func clamp[T cmp.Ordered](v, low, high T) T { + if high < low { + high, low = low, high + } + return min(high, max(low, v)) +} + +// 4-bit color constants. +const ( + Black ansi.BasicColor = iota + Red + Green + Yellow + Blue + Magenta + Cyan + White + + BrightBlack + BrightRed + BrightGreen + BrightYellow + BrightBlue + BrightMagenta + BrightCyan + BrightWhite +) + +var noColor = NoColor{} + +// NoColor is used to specify the absence of color styling. When this is active +// foreground colors will be rendered with the terminal's default text color, +// and background colors will not be drawn at all. +// +// Example usage: +// +// var style = someStyle.Background(lipgloss.NoColor{}) +type NoColor struct{} + +// RGBA returns the RGBA value of this color. Because we have to return +// something, despite this color being the absence of color, we're returning +// black with 100% opacity. +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +func (n NoColor) RGBA() (r, g, b, a uint32) { + return 0x0, 0x0, 0x0, 0xFFFF //nolint:mnd +} + +// Color specifies a color by hex or ANSI256 value. For example: +// +// ansiColor := lipgloss.Color("1") // The same as lipgloss.Red +// ansi256Color := lipgloss.Color("21") +// hexColor := lipgloss.Color("#0000ff") +func Color(s string) color.Color { + if strings.HasPrefix(s, "#") { + c, err := parseHex(s) + if err != nil { + return noColor + } + return c + } + + i, err := strconv.Atoi(s) + if err != nil { + return noColor + } + + if i < 0 { + // Only positive numbers + i = -i + } + + if i < 16 { + return ansi.BasicColor(i) //nolint:gosec + } else if i < 256 { + return ANSIColor(i) //nolint:gosec + } + + r, g, b := uint8((i>>16)&0xff), uint8(i>>8&0xff), uint8(i&0xff) //nolint:gosec + return color.RGBA{R: r, G: g, B: b, A: 0xff} +} + +var errInvalidFormat = errors.New("invalid hex format") // pre-allocated. + +// parseHex parses a hex color string and returns a color.RGBA. The string can be +// in the format #RRGGBB or #RGB. This is a more performant implementation of +// [colorful.Hex]. +func parseHex(s string) (c color.RGBA, err error) { + c.A = 0xff + + if len(s) == 0 || s[0] != '#' { + return c, errInvalidFormat + } + + hexToByte := func(b byte) byte { + switch { + case b >= '0' && b <= '9': + return b - '0' + case b >= 'a' && b <= 'f': + return b - 'a' + 10 + case b >= 'A' && b <= 'F': + return b - 'A' + 10 + } + err = errInvalidFormat + return 0 + } + + switch len(s) { + case 7: + c.R = hexToByte(s[1])<<4 + hexToByte(s[2]) + c.G = hexToByte(s[3])<<4 + hexToByte(s[4]) + c.B = hexToByte(s[5])<<4 + hexToByte(s[6]) + case 4: + c.R = hexToByte(s[1]) * 17 + c.G = hexToByte(s[2]) * 17 + c.B = hexToByte(s[3]) * 17 + default: + err = errInvalidFormat + } + return c, err +} + +// RGBColor is a color specified by red, green, and blue values. +type RGBColor struct { + R uint8 + G uint8 + B uint8 +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. +func (c RGBColor) RGBA() (r, g, b, a uint32) { + const shift = 8 + r |= uint32(c.R) << shift + g |= uint32(c.G) << shift + b |= uint32(c.B) << shift + a = 0xFFFF + return +} + +// ANSIColor is a color specified by an ANSI256 color value. +// +// Example usage: +// +// colorA := lipgloss.ANSIColor(8) +// colorB := lipgloss.ANSIColor(134) +type ANSIColor = ansi.IndexedColor + +// LightDarkFunc is a function that returns a color based on whether the +// terminal has a light or dark background. You can create one of these with +// [LightDark]. +// +// Example: +// +// lightDark := lipgloss.LightDark(hasDarkBackground) +// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff") +// myHotColor := lightDark(red, blue) +// +// For more info see [LightDark]. +type LightDarkFunc func(light, dark color.Color) color.Color + +// LightDark is a simple helper type that can be used to choose the appropriate +// color based on whether the terminal has a light or dark background. +// +// lightDark := lipgloss.LightDark(hasDarkBackground) +// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff") +// myHotColor := lightDark(red, blue) +// +// In practice, there are slightly different workflows between Bubble Tea and +// Lip Gloss standalone. +// +// In Bubble Tea, listen for tea.BackgroundColorMsg, which automatically +// flows through Update on start. This message will be received whenever the +// background color changes: +// +// case tea.BackgroundColorMsg: +// m.hasDarkBackground = msg.IsDark() +// +// Later, when you're rendering use: +// +// lightDark := lipgloss.LightDark(m.hasDarkBackground) +// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff") +// myHotColor := lightDark(red, blue) +// +// In standalone Lip Gloss, the workflow is simpler: +// +// hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout) +// lightDark := lipgloss.LightDark(hasDarkBG) +// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff") +// myHotColor := lightDark(red, blue) +func LightDark(isDark bool) LightDarkFunc { + return func(light, dark color.Color) color.Color { + if isDark { + return dark + } + return light + } +} + +// isDarkColor returns whether the given color is dark (based on the luminance +// portion of the color as interpreted as HSL). +// +// Example usage: +// +// color := lipgloss.Color("#0000ff") +// if lipgloss.isDarkColor(color) { +// fmt.Println("It's dark! I love darkness!") +// } else { +// fmt.Println("It's light! Cover your eyes!") +// } +func isDarkColor(c color.Color) bool { + col, ok := colorful.MakeColor(c) + if !ok { + return true + } + + _, _, l := col.Hsl() + return l < 0.5 //nolint:mnd +} + +// CompleteFunc is a function that returns the appropriate color based on the +// given color profile. +// +// Example usage: +// +// p := colorprofile.Detect(os.Stderr, os.Environ()) +// complete := lipgloss.Complete(p) +// color := complete( +// lipgloss.Color(1), // ANSI +// lipgloss.Color(124), // ANSI256 +// lipgloss.Color("#ff34ac"), // TrueColor +// ) +// fmt.Println("Ooh, pretty color: ", color) +// +// For more info see [Complete]. +type CompleteFunc func(ansi, ansi256, truecolor color.Color) color.Color + +// Complete returns a function that will return the appropriate color based on +// the given color profile. +// +// Example usage: +// +// p := colorprofile.Detect(os.Stderr, os.Environ()) +// complete := lipgloss.Complete(p) +// color := complete( +// lipgloss.Color(1), // ANSI +// lipgloss.Color(124), // ANSI256 +// lipgloss.Color("#ff34ac"), // TrueColor +// ) +// fmt.Println("Ooh, pretty color: ", color) +func Complete(p colorprofile.Profile) CompleteFunc { + return func(ansi, ansi256, truecolor color.Color) color.Color { + switch p { //nolint:exhaustive + case colorprofile.ANSI: + return ansi + case colorprofile.ANSI256: + return ansi256 + case colorprofile.TrueColor: + return truecolor + } + return noColor + } +} + +// ensureNotTransparent ensures that the alpha value of a color is not 0, and if +// it is, we will set it to 1. This is useful for when we are converting from +// RGB -> RGBA, and the alpha value is lost in the conversion for gradient purposes. +func ensureNotTransparent(c color.Color) color.Color { + _, _, _, a := c.RGBA() + if a == 0 { + return Alpha(c, 1) + } + return c +} + +// Alpha adjusts the alpha value of a color using a 0-1 (clamped) float scale +// 0 = transparent, 1 = opaque. +func Alpha(c color.Color, alpha float64) color.Color { + if c == nil { + return nil + } + + r, g, b, _ := c.RGBA() + return color.RGBA{ + R: uint8(min(255, float64(r>>8))), + G: uint8(min(255, float64(g>>8))), + B: uint8(min(255, float64(b>>8))), + A: uint8(clamp(alpha, 0, 1) * 255), + } +} + +// Complementary returns the complementary color (180° away on color wheel) of +// the given color. This is useful for creating a contrasting color. +func Complementary(c color.Color) color.Color { + if c == nil { + return nil + } + + // Offset hue by 180°. + cf, _ := colorful.MakeColor(ensureNotTransparent(c)) + + h, s, v := cf.Hsv() + h += 180 + if h >= 360 { + h -= 360 + } else if h < 0 { + h += 360 + } + + return colorful.Hsv(h, s, v).Clamped() +} + +// Darken takes a color and makes it darker by a specific percentage (0-1, clamped). +func Darken(c color.Color, percent float64) color.Color { + if c == nil { + return nil + } + + mult := 1.0 - clamp(percent, 0, 1) + + r, g, b, a := c.RGBA() + return color.RGBA{ + R: uint8(float64(r>>8) * mult), + G: uint8(float64(g>>8) * mult), + B: uint8(float64(b>>8) * mult), + A: uint8(min(255, float64(a>>8))), + } +} + +// Lighten makes a color lighter by a specific percentage (0-1, clamped). +func Lighten(c color.Color, percent float64) color.Color { + if c == nil { + return nil + } + + add := 255 * (clamp(percent, 0, 1)) + + r, g, b, a := c.RGBA() + return color.RGBA{ + R: uint8(min(255, float64(r>>8)+add)), + G: uint8(min(255, float64(g>>8)+add)), + B: uint8(min(255, float64(b>>8)+add)), + A: uint8(min(255, float64(a>>8))), + } +} diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/get.go b/tools/vendor/charm.land/lipgloss/v2/get.go similarity index 80% rename from tools/vendor/github.com/charmbracelet/lipgloss/get.go rename to tools/vendor/charm.land/lipgloss/v2/get.go index 422b4ce95..d1fe1d669 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/get.go +++ b/tools/vendor/charm.land/lipgloss/v2/get.go @@ -1,6 +1,7 @@ package lipgloss import ( + "image/color" "strings" "github.com/charmbracelet/x/ansi" @@ -20,7 +21,19 @@ func (s Style) GetItalic() bool { // GetUnderline returns the style's underline value. If no value is set false is // returned. func (s Style) GetUnderline() bool { - return s.getAsBool(underlineKey, false) + return s.ul != UnderlineNone +} + +// GetUnderlineStyle returns the style's underline style. If no value is set +// UnderlineNone is returned. +func (s Style) GetUnderlineStyle() Underline { + return s.ul +} + +// GetUnderlineColor returns the style's underline color. If no value is set +// NoColor{} is returned. +func (s Style) GetUnderlineColor() color.Color { + return s.getAsColor(underlineColorKey) } // GetStrikethrough returns the style's strikethrough value. If no value is set false @@ -49,13 +62,13 @@ func (s Style) GetFaint() bool { // GetForeground returns the style's foreground color. If no value is set // NoColor{} is returned. -func (s Style) GetForeground() TerminalColor { +func (s Style) GetForeground() color.Color { return s.getAsColor(foregroundKey) } // GetBackground returns the style's background color. If no value is set // NoColor{} is returned. -func (s Style) GetBackground() TerminalColor { +func (s Style) GetBackground() color.Color { return s.getAsColor(backgroundKey) } @@ -134,6 +147,16 @@ func (s Style) GetPaddingLeft() int { return s.getAsInt(paddingLeftKey) } +// GetPaddingChar returns the style's padding character. If no value is set a +// space is returned. +func (s Style) GetPaddingChar() rune { + char := s.getAsRune(paddingCharKey) + if char == 0 { + return ' ' + } + return char +} + // GetHorizontalPadding returns the style's left and right padding. Unset // values are measured as 0. func (s Style) GetHorizontalPadding() int { @@ -185,6 +208,16 @@ func (s Style) GetMarginLeft() int { return s.getAsInt(marginLeftKey) } +// GetMarginChar returns the style's padding character. If no value is set a +// space is returned. +func (s Style) GetMarginChar() rune { + char := s.getAsRune(marginCharKey) + if char == 0 { + return ' ' + } + return char +} + // GetHorizontalMargins returns the style's left and right margins. Unset // values are measured as 0. func (s Style) GetHorizontalMargins() int { @@ -241,49 +274,61 @@ func (s Style) GetBorderLeft() bool { // GetBorderTopForeground returns the style's border top foreground color. If // no value is set NoColor{} is returned. -func (s Style) GetBorderTopForeground() TerminalColor { +func (s Style) GetBorderTopForeground() color.Color { return s.getAsColor(borderTopForegroundKey) } // GetBorderRightForeground returns the style's border right foreground color. // If no value is set NoColor{} is returned. -func (s Style) GetBorderRightForeground() TerminalColor { +func (s Style) GetBorderRightForeground() color.Color { return s.getAsColor(borderRightForegroundKey) } // GetBorderBottomForeground returns the style's border bottom foreground // color. If no value is set NoColor{} is returned. -func (s Style) GetBorderBottomForeground() TerminalColor { +func (s Style) GetBorderBottomForeground() color.Color { return s.getAsColor(borderBottomForegroundKey) } // GetBorderLeftForeground returns the style's border left foreground // color. If no value is set NoColor{} is returned. -func (s Style) GetBorderLeftForeground() TerminalColor { +func (s Style) GetBorderLeftForeground() color.Color { return s.getAsColor(borderLeftForegroundKey) } +// GetBorderForegroundBlend returns the style's border blend foreground +// colors. If no value is set, nil is returned. +func (s Style) GetBorderForegroundBlend() []color.Color { + return s.getAsColors(borderForegroundBlendKey) +} + +// GetBorderForegroundBlendOffset returns the style's border blend offset. If no +// value is set, 0 is returned. +func (s Style) GetBorderForegroundBlendOffset() int { + return s.getAsInt(borderForegroundBlendOffsetKey) +} + // GetBorderTopBackground returns the style's border top background color. If // no value is set NoColor{} is returned. -func (s Style) GetBorderTopBackground() TerminalColor { +func (s Style) GetBorderTopBackground() color.Color { return s.getAsColor(borderTopBackgroundKey) } // GetBorderRightBackground returns the style's border right background color. // If no value is set NoColor{} is returned. -func (s Style) GetBorderRightBackground() TerminalColor { +func (s Style) GetBorderRightBackground() color.Color { return s.getAsColor(borderRightBackgroundKey) } // GetBorderBottomBackground returns the style's border bottom background // color. If no value is set NoColor{} is returned. -func (s Style) GetBorderBottomBackground() TerminalColor { +func (s Style) GetBorderBottomBackground() color.Color { return s.getAsColor(borderBottomBackgroundKey) } // GetBorderLeftBackground returns the style's border left background // color. If no value is set NoColor{} is returned. -func (s Style) GetBorderLeftBackground() TerminalColor { +func (s Style) GetBorderLeftBackground() color.Color { return s.getAsColor(borderLeftBackgroundKey) } @@ -300,7 +345,10 @@ func (s Style) GetBorderTopWidth() int { // runes of varying widths, the widest rune is returned. If no border exists on // the top edge, 0 is returned. func (s Style) GetBorderTopSize() int { - if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() { + if s.isBorderStyleSetWithoutSides() { + return 1 + } + if !s.getAsBool(borderTopKey, false) { return 0 } return s.getBorderStyle().GetTopSize() @@ -310,7 +358,10 @@ func (s Style) GetBorderTopSize() int { // runes of varying widths, the widest rune is returned. If no border exists on // the left edge, 0 is returned. func (s Style) GetBorderLeftSize() int { - if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() { + if s.isBorderStyleSetWithoutSides() { + return 1 + } + if !s.getAsBool(borderLeftKey, false) { return 0 } return s.getBorderStyle().GetLeftSize() @@ -320,7 +371,10 @@ func (s Style) GetBorderLeftSize() int { // contain runes of varying widths, the widest rune is returned. If no border // exists on the left edge, 0 is returned. func (s Style) GetBorderBottomSize() int { - if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() { + if s.isBorderStyleSetWithoutSides() { + return 1 + } + if !s.getAsBool(borderBottomKey, false) { return 0 } return s.getBorderStyle().GetBottomSize() @@ -330,7 +384,10 @@ func (s Style) GetBorderBottomSize() int { // contain runes of varying widths, the widest rune is returned. If no border // exists on the right edge, 0 is returned. func (s Style) GetBorderRightSize() int { - if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() { + if s.isBorderStyleSetWithoutSides() { + return 1 + } + if !s.getAsBool(borderRightKey, false) { return 0 } return s.getBorderStyle().GetRightSize() @@ -414,11 +471,36 @@ func (s Style) GetTransform() func(string) string { return s.getAsTransform(transformKey) } +// GetHyperlink returns the hyperlink along with its parameters. If no +// hyperlink is set, empty strings are returned. +func (s Style) GetHyperlink() (link, params string) { + if s.isSet(linkKey) { + link = s.link + } + if s.isSet(linkParamsKey) { + params = s.linkParams + } + return +} + // Returns whether or not the given property is set. func (s Style) isSet(k propKey) bool { return s.props.has(k) } +func (s Style) getAsRune(k propKey) rune { + if !s.isSet(k) { + return 0 + } + switch k { //nolint:exhaustive + case paddingCharKey: + return s.paddingChar + case marginCharKey: + return s.marginChar + } + return 0 +} + func (s Style) getAsBool(k propKey, defaultVal bool) bool { if !s.isSet(k) { return defaultVal @@ -426,12 +508,25 @@ func (s Style) getAsBool(k propKey, defaultVal bool) bool { return s.attrs&int(k) != 0 } -func (s Style) getAsColor(k propKey) TerminalColor { +func (s Style) getAsColors(k propKey) (colors []color.Color) { + if !s.isSet(k) { + return nil + } + + switch k { //nolint:exhaustive + case borderForegroundBlendKey: + return s.borderBlendFgColor + } + + return nil +} + +func (s Style) getAsColor(k propKey) color.Color { if !s.isSet(k) { return noColor } - var c TerminalColor + var c color.Color switch k { //nolint:exhaustive case foregroundKey: c = s.fgColor @@ -455,6 +550,8 @@ func (s Style) getAsColor(k propKey) TerminalColor { c = s.borderBottomBgColor case borderLeftBackgroundKey: c = s.borderLeftBgColor + case underlineColorKey: + c = s.ulColor } if c != nil { @@ -489,6 +586,8 @@ func (s Style) getAsInt(k propKey) int { return s.marginBottom case marginLeftKey: return s.marginLeft + case borderForegroundBlendOffsetKey: + return s.borderForegroundBlendOffset case maxWidthKey: return s.maxWidth case maxHeightKey: @@ -519,20 +618,6 @@ func (s Style) getBorderStyle() Border { return s.borderStyle } -// Returns whether or not the style has implicit borders. This happens when -// a border style has been set but no border sides have been explicitly turned -// on or off. -func (s Style) implicitBorders() bool { - var ( - borderStyle = s.getBorderStyle() - topSet = s.isSet(borderTopKey) - rightSet = s.isSet(borderRightKey) - bottomSet = s.isSet(borderBottomKey) - leftSet = s.isSet(borderLeftKey) - ) - return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet) -} - func (s Style) getAsTransform(propKey) func(string) string { if !s.isSet(transformKey) { return nil @@ -543,6 +628,8 @@ func (s Style) getAsTransform(propKey) func(string) string { // Split a string into lines, additionally returning the size of the widest // line. func getLines(s string) (lines []string, widest int) { + s = strings.ReplaceAll(s, "\t", " ") + s = strings.ReplaceAll(s, "\r\n", "\n") lines = strings.Split(s, "\n") for _, l := range lines { @@ -554,3 +641,17 @@ func getLines(s string) (lines []string, widest int) { return lines, widest } + +// isBorderStyleSetWithoutSides returns true if the border style is set but no +// sides are set. This is used to determine if the border should be rendered by +// default. +func (s Style) isBorderStyleSetWithoutSides() bool { + var ( + border = s.getBorderStyle() + topSet = s.isSet(borderTopKey) + rightSet = s.isSet(borderRightKey) + bottomSet = s.isSet(borderBottomKey) + leftSet = s.isSet(borderLeftKey) + ) + return border != noBorder && !(topSet || rightSet || bottomSet || leftSet) //nolint:staticcheck +} diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/join.go b/tools/vendor/charm.land/lipgloss/v2/join.go similarity index 97% rename from tools/vendor/github.com/charmbracelet/lipgloss/join.go rename to tools/vendor/charm.land/lipgloss/v2/join.go index b0a23a546..349ae552f 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/join.go +++ b/tools/vendor/charm.land/lipgloss/v2/join.go @@ -60,7 +60,7 @@ func JoinHorizontal(pos Position, strs ...string) string { extraLines := make([]string, maxHeight-len(blocks[i])) - switch pos { //nolint:exhaustive + switch pos { case Top: blocks[i] = append(blocks[i], extraLines...) @@ -139,7 +139,7 @@ func JoinVertical(pos Position, strs ...string) string { for j, line := range block { w := maxWidth - ansi.StringWidth(line) - switch pos { //nolint:exhaustive + switch pos { case Left: b.WriteString(line) b.WriteString(strings.Repeat(" ", w)) @@ -165,7 +165,7 @@ func JoinVertical(pos Position, strs ...string) string { // Write a newline as long as we're not on the last line of the // last block. - if !(i == len(blocks)-1 && j == len(block)-1) { + if !(i == len(blocks)-1 && j == len(block)-1) { //nolint:staticcheck b.WriteRune('\n') } } diff --git a/tools/vendor/charm.land/lipgloss/v2/layer.go b/tools/vendor/charm.land/lipgloss/v2/layer.go new file mode 100644 index 000000000..e30d1ef2a --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/layer.go @@ -0,0 +1,327 @@ +package lipgloss + +import ( + "fmt" + "image" + "slices" + + uv "github.com/charmbracelet/ultraviolet" +) + +// Layer represents a visual layer with content and positioning. It's a pure +// data structure that defines the layer hierarchy without any computation. +type Layer struct { + id string + content string + width, height int + x, y, z int + layers []*Layer +} + +// NewLayer creates a new [Layer] with the given content and optional child layers. +func NewLayer(content string, layers ...*Layer) *Layer { + l := &Layer{ + content: content, + } + l.AddLayers(layers...) + return l +} + +// GetContent returns the content of the Layer. +func (l *Layer) GetContent() string { + return l.content +} + +// Width returns the width of the Layer. +func (l *Layer) Width() int { + return l.width +} + +// Height returns the height of the Layer. +func (l *Layer) Height() int { + return l.height +} + +// GetID returns the ID of the Layer. +func (l *Layer) GetID() string { + return l.id +} + +// ID sets the ID of the Layer. +func (l *Layer) ID(id string) *Layer { + l.id = id + return l +} + +// X sets the x-coordinate of the Layer relative to its parent. +func (l *Layer) X(x int) *Layer { + l.x = x + return l +} + +// Y sets the y-coordinate of the Layer relative to its parent. +func (l *Layer) Y(y int) *Layer { + l.y = y + return l +} + +// Z sets the z-index of the Layer relative to its parent. +func (l *Layer) Z(z int) *Layer { + l.z = z + return l +} + +// GetX returns the x-coordinate of the Layer relative to its parent. +func (l *Layer) GetX() int { + return l.x +} + +// GetY returns the y-coordinate of the Layer relative to its parent. +func (l *Layer) GetY() int { + return l.y +} + +// GetZ returns the z-index of the Layer relative to its parent. +func (l *Layer) GetZ() int { + return l.z +} + +// AddLayers adds child layers to the Layer. +func (l *Layer) AddLayers(layers ...*Layer) *Layer { + for i, layer := range layers { + if layer == nil { + panic(fmt.Sprintf("layer at index %d is nil", i)) + } + l.layers = append(l.layers, layer) + } + area := l.boundsWithOffset(0, 0) + l.width = area.Dx() + l.height = area.Dy() + return l +} + +// GetLayer returns a descendant layer by its ID, or nil if not found. +// Layers with empty IDs are skipped. +func (l *Layer) GetLayer(id string) *Layer { + if id == "" { + return nil + } + if l.id == id { + return l + } + for _, child := range l.layers { + if found := child.GetLayer(id); found != nil { + return found + } + } + return nil +} + +// MaxZ returns the maximum z-index among this layer and all its descendants. +func (l *Layer) MaxZ() int { + maxZ := l.z + for _, child := range l.layers { + childMaxZ := child.MaxZ() + if childMaxZ > maxZ { + maxZ = childMaxZ + } + } + return maxZ +} + +// boundsWithOffset calculates bounds with parent offset applied. +func (l *Layer) boundsWithOffset(parentX, parentY int) image.Rectangle { + absX := l.x + parentX + absY := l.y + parentY + + width, height := Width(l.content), Height(l.content) + bounds := image.Rectangle{ + Min: image.Pt(absX, absY), + Max: image.Pt(absX+width, absY+height), + } + + for _, child := range l.layers { + bounds = bounds.Union(child.boundsWithOffset(absX, absY)) + } + + return bounds +} + +var _ uv.Drawable = (*Layer)(nil) + +// Draw draws the content of the layer on the screen at the specified area. +func (l *Layer) Draw(scr uv.Screen, area uv.Rectangle) { + content := uv.NewStyledString(l.content) + content.Draw(scr, area) +} + +// LayerHit represents the result of a hit test on a [Layer]. +type LayerHit struct { + id string + layer *Layer + bounds image.Rectangle +} + +// Empty returns true if the LayerHit represents no hit. +func (lh LayerHit) Empty() bool { + return lh.layer == nil +} + +// ID returns the ID of the hit Layer. +func (lh LayerHit) ID() string { + return lh.id +} + +// Layer returns the layer that was hit. +func (lh LayerHit) Layer() *Layer { + return lh.layer +} + +// Bounds returns the bounds of the LayerHit. +func (lh LayerHit) Bounds() image.Rectangle { + return lh.bounds +} + +// Compositor manages the composition of layers. It flattens a layer hierarchy +// once and provides efficient drawing and hit testing operations. All computation +// related to layers happens in the Compositor. +type Compositor struct { + root *Layer + layers []compositeLayer + index map[string]*Layer + bounds image.Rectangle +} + +// compositeLayer holds a flattened layer with its calculated absolute position and bounds. +type compositeLayer struct { + layer *Layer + absX int + absY int + bounds image.Rectangle +} + +// NewCompositor creates a new Compositor with an internal root layer. Optional +// layers can be provided which will be added as children of the root. The layer +// hierarchy is flattened and sorted by z-index for efficient rendering and hit testing. +func NewCompositor(layers ...*Layer) *Compositor { + root := NewLayer("") + root.AddLayers(layers...) + c := &Compositor{ + root: root, + index: make(map[string]*Layer), + } + c.flatten() + return c +} + +// AddLayers adds layers to the compositor's root and refreshes the internal state. +func (c *Compositor) AddLayers(layers ...*Layer) *Compositor { + c.root.AddLayers(layers...) + c.flatten() + return c +} + +// flatten builds the internal flattened layer list and calculates overall bounds. +func (c *Compositor) flatten() { + c.layers = nil + c.index = make(map[string]*Layer) + c.flattenRecursive(c.root, 0, 0) + + // Sort by absolute z-index (lowest to highest for drawing) + slices.SortFunc(c.layers, func(a, b compositeLayer) int { + return a.layer.z - b.layer.z + }) + + // Calculate overall bounds + if len(c.layers) > 0 { + c.bounds = c.layers[0].bounds + for i := 1; i < len(c.layers); i++ { + c.bounds = c.bounds.Union(c.layers[i].bounds) + } + } +} + +// flattenRecursive recursively collects all layers with their absolute positions. +func (c *Compositor) flattenRecursive(layer *Layer, parentX, parentY int) { + absX := layer.x + parentX + absY := layer.y + parentY + + width, height := Width(layer.content), Height(layer.content) + bounds := image.Rectangle{ + Min: image.Pt(absX, absY), + Max: image.Pt(absX+width, absY+height), + } + + c.layers = append(c.layers, compositeLayer{ + layer: layer, + absX: absX, + absY: absY, + bounds: bounds, + }) + + // Index layer by ID if it has one + if layer.id != "" { + c.index[layer.id] = layer + } + + for _, child := range layer.layers { + c.flattenRecursive(child, absX, absY) + } +} + +// Bounds returns the overall bounds of all layers in the compositor. +func (c *Compositor) Bounds() image.Rectangle { + return c.bounds +} + +// Draw draws all layers onto the given [uv.Screen] in z-index order. +func (c *Compositor) Draw(scr uv.Screen, area image.Rectangle) { + for _, cl := range c.layers { + if cl.bounds.Overlaps(area) { + cl.layer.Draw(scr, cl.bounds) + } + } +} + +// Hit performs a hit test at the given (x, y) coordinates. If a layer is hit, +// it returns the ID of the top-most layer at that point. Layers with empty IDs +// are ignored. If no layer is hit, it returns an empty [LayerHit]. +func (c *Compositor) Hit(x, y int) LayerHit { + var hit LayerHit + pt := image.Pt(x, y) + // Check from highest z to lowest (reverse order) + for i := len(c.layers) - 1; i >= 0; i-- { + cl := c.layers[i] + if cl.layer.id != "" && pt.In(cl.bounds) { + hit.id = cl.layer.id + hit.layer = cl.layer + hit.bounds = cl.bounds + return hit + } + } + return hit +} + +// GetLayer returns a layer by its ID, or nil if not found. +// Layers with empty IDs are not indexed and cannot be retrieved. +func (c *Compositor) GetLayer(id string) *Layer { + if id == "" { + return nil + } + return c.index[id] +} + +// Refresh re-flattens the layer hierarchy. Call this after modifying the layer +// tree structure or positions to update the compositor's internal state. +func (c *Compositor) Refresh() { + c.flatten() +} + +// Render renders the compositor into a styled string. This is a helper +// function that creates a temporary canvas, draws the compositor onto it, and +// returns the resulting string. +func (c *Compositor) Render() string { + width, height := c.bounds.Dx(), c.bounds.Dy() + canvas := NewCanvas(width, height) + return canvas.Compose(c).Render() +} diff --git a/tools/vendor/charm.land/lipgloss/v2/lipgloss.go b/tools/vendor/charm.land/lipgloss/v2/lipgloss.go new file mode 100644 index 000000000..3fb4e6f26 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/lipgloss.go @@ -0,0 +1,3 @@ +// Package lipgloss provides style definitions for nice terminal layouts. Built +// with TUIs in mind. +package lipgloss diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/position.go b/tools/vendor/charm.land/lipgloss/v2/position.go similarity index 69% rename from tools/vendor/github.com/charmbracelet/lipgloss/position.go rename to tools/vendor/charm.land/lipgloss/v2/position.go index 185f5af3b..cea67763f 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/position.go +++ b/tools/vendor/charm.land/lipgloss/v2/position.go @@ -34,26 +34,13 @@ const ( // Place places a string or text block vertically in an unstyled box of a given // width or height. func Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string { - return renderer.Place(width, height, hPos, vPos, str, opts...) -} - -// Place places a string or text block vertically in an unstyled box of a given -// width or height. -func (r *Renderer) Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string { - return r.PlaceVertical(height, vPos, r.PlaceHorizontal(width, hPos, str, opts...), opts...) + return PlaceVertical(height, vPos, PlaceHorizontal(width, hPos, str, opts...), opts...) } // PlaceHorizontal places a string or text block horizontally in an unstyled // block of a given width. If the given width is shorter than the max width of // the string (measured by its longest line) this will be a noop. func PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string { - return renderer.PlaceHorizontal(width, pos, str, opts...) -} - -// PlaceHorizontal places a string or text block horizontally in an unstyled -// block of a given width. If the given width is shorter than the max width of -// the string (measured by its longest line) this will be a noöp. -func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string { lines, contentWidth := getLines(str) gap := width - contentWidth @@ -61,14 +48,14 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ... return str } - ws := newWhitespace(r, opts...) + ws := newWhitespace(opts...) var b strings.Builder for i, l := range lines { // Is this line shorter than the longest line? short := max(0, contentWidth-ansi.StringWidth(l)) - switch pos { //nolint:exhaustive + switch pos { case Left: b.WriteString(l) b.WriteString(ws.render(gap + short)) @@ -101,13 +88,6 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ... // of a given height. If the given height is shorter than the height of the // string (measured by its newlines) then this will be a noop. func PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string { - return renderer.PlaceVertical(height, pos, str, opts...) -} - -// PlaceVertical places a string or text block vertically in an unstyled block -// of a given height. If the given height is shorter than the height of the -// string (measured by its newlines) then this will be a noöp. -func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string { contentHeight := strings.Count(str, "\n") + 1 gap := height - contentHeight @@ -115,17 +95,17 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W return str } - ws := newWhitespace(r, opts...) + ws := newWhitespace(opts...) _, width := getLines(str) emptyLine := ws.render(width) b := strings.Builder{} - switch pos { //nolint:exhaustive + switch pos { case Top: b.WriteString(str) b.WriteRune('\n') - for i := 0; i < gap; i++ { + for i := range gap { b.WriteString(emptyLine) if i < gap-1 { b.WriteRune('\n') @@ -144,7 +124,7 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W b.WriteString(strings.Repeat(emptyLine+"\n", top)) b.WriteString(str) - for i := 0; i < bottom; i++ { + for range bottom { b.WriteRune('\n') b.WriteString(emptyLine) } diff --git a/tools/vendor/charm.land/lipgloss/v2/query.go b/tools/vendor/charm.land/lipgloss/v2/query.go new file mode 100644 index 000000000..96cd5b945 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/query.go @@ -0,0 +1,92 @@ +package lipgloss + +import ( + "fmt" + "image/color" + "os" + "runtime" + + "github.com/charmbracelet/x/term" +) + +func backgroundColor(in term.File, out term.File) (color.Color, error) { + state, err := term.MakeRaw(in.Fd()) + if err != nil { + return nil, fmt.Errorf("error setting raw state to detect background color: %w", err) + } + + defer term.Restore(in.Fd(), state) //nolint:errcheck + + bg, err := queryBackgroundColor(in, out) + if err != nil { + return nil, err + } + + return bg, nil +} + +// BackgroundColor queries the terminal's background color. Typically, you'll +// want to query against stdin and either stdout or stderr, depending on what +// you're writing to. +// +// This function is intended for standalone Lip Gloss use only. If you're using +// Bubble Tea, listen for tea.BackgroundColorMsg in your update function. +func BackgroundColor(in term.File, out term.File) (bg color.Color, err error) { + if runtime.GOOS == "windows" { //nolint:nestif + // On Windows, when the input/output is redirected or piped, we need to + // open the console explicitly. + // See https://learn.microsoft.com/en-us/windows/console/getstdhandle#remarks + if !term.IsTerminal(in.Fd()) { + f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644) //nolint:gosec + if err != nil { + return nil, fmt.Errorf("error opening CONIN$: %w", err) + } + in = f + } + if !term.IsTerminal(out.Fd()) { + f, err := os.OpenFile("CONOUT$", os.O_RDWR, 0o644) //nolint:gosec + if err != nil { + return nil, fmt.Errorf("error opening CONOUT$: %w", err) + } + out = f + } + return backgroundColor(in, out) + } + + // NOTE: On Unix, one of the given files must be a tty. + if !term.IsTerminal(in.Fd()) || !term.IsTerminal(out.Fd()) { + return nil, fmt.Errorf("input/output is not a terminal") + } + for _, f := range []term.File{in, out} { + if bg, err = backgroundColor(f, f); err == nil { + return bg, nil + } + } + + return bg, err +} + +// HasDarkBackground detects whether the terminal has a light or dark +// background. +// +// Typically, you'll want to query against stdin and either stdout or stderr +// depending on what you're writing to. +// +// hasDarkBG := HasDarkBackground(os.Stdin, os.Stdout) +// lightDark := LightDark(hasDarkBG) +// myHotColor := lightDark("#ff0000", "#0000ff") +// +// This is intended for use in standalone Lip Gloss only. In Bubble Tea, listen +// for tea.BackgroundColorMsg in your Update function. +// +// case tea.BackgroundColorMsg: +// hasDarkBackground = msg.IsDark() +// +// By default, this function will return true if it encounters an error. +func HasDarkBackground(in term.File, out term.File) bool { + bg, err := BackgroundColor(in, out) + if err != nil || bg == nil { + return true + } + return isDarkColor(bg) +} diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/ranges.go b/tools/vendor/charm.land/lipgloss/v2/ranges.go similarity index 75% rename from tools/vendor/github.com/charmbracelet/lipgloss/ranges.go rename to tools/vendor/charm.land/lipgloss/v2/ranges.go index d17169987..bb209f0ea 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/ranges.go +++ b/tools/vendor/charm.land/lipgloss/v2/ranges.go @@ -6,9 +6,8 @@ import ( "github.com/charmbracelet/x/ansi" ) -// StyleRanges allows to, given a string, style ranges of it differently. -// The function will take into account existing styles. -// Ranges should not overlap. +// StyleRanges applying styling to ranges in a string. Existing styles will be +// taken into account. Ranges should not overlap. func StyleRanges(s string, ranges ...Range) string { if len(ranges) == 0 { return s @@ -36,12 +35,13 @@ func StyleRanges(s string, ranges ...Range) string { return buf.String() } -// NewRange returns a range that can be used with [StyleRanges]. +// NewRange returns a range and style that can be used with [StyleRanges]. func NewRange(start, end int, style Style) Range { return Range{start, end, style} } -// Range to be used with [StyleRanges]. +// Range is a range of text and associated styling to be used with +// [StyleRanges]. type Range struct { Start, End int Style Style diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/runes.go b/tools/vendor/charm.land/lipgloss/v2/runes.go similarity index 100% rename from tools/vendor/github.com/charmbracelet/lipgloss/runes.go rename to tools/vendor/charm.land/lipgloss/v2/runes.go diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/set.go b/tools/vendor/charm.land/lipgloss/v2/set.go similarity index 78% rename from tools/vendor/github.com/charmbracelet/lipgloss/set.go rename to tools/vendor/charm.land/lipgloss/v2/set.go index fde38faec..f10b4538a 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/set.go +++ b/tools/vendor/charm.land/lipgloss/v2/set.go @@ -1,16 +1,25 @@ package lipgloss +import ( + "image/color" + "strings" +) + // Set a value on the underlying rules map. -func (s *Style) set(key propKey, value interface{}) { +func (s *Style) set(key propKey, value any) { // We don't allow negative integers on any of our other values, so just keep // them at zero or above. We could use uints instead, but the // conversions are a little tedious, so we're sticking with ints for // sake of usability. - switch key { //nolint:exhaustive + switch key { case foregroundKey: s.fgColor = colorOrNil(value) case backgroundKey: s.bgColor = colorOrNil(value) + case underlineColorKey: + s.ulColor = colorOrNil(value) + case underlineKey: + s.ul = value.(Underline) case widthKey: s.width = max(0, value.(int)) case heightKey: @@ -27,6 +36,8 @@ func (s *Style) set(key propKey, value interface{}) { s.paddingBottom = max(0, value.(int)) case paddingLeftKey: s.paddingLeft = max(0, value.(int)) + case paddingCharKey: + s.paddingChar = value.(rune) case marginTopKey: s.marginTop = max(0, value.(int)) case marginRightKey: @@ -37,6 +48,8 @@ func (s *Style) set(key propKey, value interface{}) { s.marginLeft = max(0, value.(int)) case marginBackgroundKey: s.marginBgColor = colorOrNil(value) + case marginCharKey: + s.marginChar = value.(rune) case borderStyleKey: s.borderStyle = value.(Border) case borderTopForegroundKey: @@ -47,6 +60,10 @@ func (s *Style) set(key propKey, value interface{}) { s.borderBottomFgColor = colorOrNil(value) case borderLeftForegroundKey: s.borderLeftFgColor = colorOrNil(value) + case borderForegroundBlendKey: + s.borderBlendFgColor = value.([]color.Color) + case borderForegroundBlendOffsetKey: + s.borderForegroundBlendOffset = value.(int) case borderTopBackgroundKey: s.borderTopBgColor = colorOrNil(value) case borderRightBackgroundKey: @@ -65,6 +82,10 @@ func (s *Style) set(key propKey, value interface{}) { s.tabWidth = value.(int) case transformKey: s.transform = value.(func(string) string) + case linkKey: + s.link = value.(string) + case linkParamsKey: + s.linkParams = value.(string) default: if v, ok := value.(bool); ok { //nolint:nestif if v { @@ -88,11 +109,15 @@ func (s *Style) set(key propKey, value interface{}) { // setFrom sets the property from another style. func (s *Style) setFrom(key propKey, i Style) { - switch key { //nolint:exhaustive + switch key { case foregroundKey: s.set(foregroundKey, i.fgColor) case backgroundKey: s.set(backgroundKey, i.bgColor) + case underlineColorKey: + s.set(underlineColorKey, i.ulColor) + case underlineKey: + s.set(underlineKey, i.ul) case widthKey: s.set(widthKey, i.width) case heightKey: @@ -109,6 +134,8 @@ func (s *Style) setFrom(key propKey, i Style) { s.set(paddingBottomKey, i.paddingBottom) case paddingLeftKey: s.set(paddingLeftKey, i.paddingLeft) + case paddingCharKey: + s.set(paddingCharKey, i.paddingChar) case marginTopKey: s.set(marginTopKey, i.marginTop) case marginRightKey: @@ -119,6 +146,8 @@ func (s *Style) setFrom(key propKey, i Style) { s.set(marginLeftKey, i.marginLeft) case marginBackgroundKey: s.set(marginBackgroundKey, i.marginBgColor) + case marginCharKey: + s.set(marginCharKey, i.marginChar) case borderStyleKey: s.set(borderStyleKey, i.borderStyle) case borderTopForegroundKey: @@ -129,6 +158,10 @@ func (s *Style) setFrom(key propKey, i Style) { s.set(borderBottomForegroundKey, i.borderBottomFgColor) case borderLeftForegroundKey: s.set(borderLeftForegroundKey, i.borderLeftFgColor) + case borderForegroundBlendKey: + s.set(borderForegroundBlendKey, i.borderBlendFgColor) + case borderForegroundBlendOffsetKey: + s.set(borderForegroundBlendOffsetKey, i.borderForegroundBlendOffset) case borderTopBackgroundKey: s.set(borderTopBackgroundKey, i.borderTopBgColor) case borderRightBackgroundKey: @@ -151,8 +184,8 @@ func (s *Style) setFrom(key propKey, i Style) { } } -func colorOrNil(c interface{}) TerminalColor { - if c, ok := c.(TerminalColor); ok { +func colorOrNil(c any) color.Color { + if c, ok := c.(color.Color); ok { return c } return nil @@ -173,9 +206,33 @@ func (s Style) Italic(v bool) Style { // Underline sets an underline rule. By default, underlines will not be drawn on // whitespace like margins and padding. To change this behavior set -// UnderlineSpaces. +// [Style.UnderlineSpaces]. func (s Style) Underline(v bool) Style { - s.set(underlineKey, v) + if v { + return s.UnderlineStyle(UnderlineSingle) + } + return s.UnderlineStyle(UnderlineNone) +} + +// UnderlineStyle sets the underline style. This can be used to set the underline +// to be a single, double, curly, dotted, or dashed line. +// +// Note that not all terminal emulators support underline styles. If a style is +// not supported, it will typically fall back to a single underline but this is +// not guaranteed. This depends on the terminal emulator being used. +func (s Style) UnderlineStyle(u Underline) Style { + s.set(underlineKey, u) + return s +} + +// UnderlineColor sets the color of the underline. By default, the underline +// will be the same color as the foreground. +// +// Note that not all terminal emulators support colored underlines. If color is +// not supported, it might produce unexpected results. This depends on the +// terminal emulator being used. +func (s Style) UnderlineColor(c color.Color) Style { + s.set(underlineColorKey, c) return s } @@ -212,19 +269,20 @@ func (s Style) Faint(v bool) Style { // // // Removes the foreground color // s.Foreground(lipgloss.NoColor) -func (s Style) Foreground(c TerminalColor) Style { +func (s Style) Foreground(c color.Color) Style { s.set(foregroundKey, c) return s } // Background sets a background color. -func (s Style) Background(c TerminalColor) Style { +func (s Style) Background(c color.Color) Style { s.set(backgroundKey, c) return s } -// Width sets the width of the block before applying margins. The width, if -// set, also determines where text will wrap. +// Width sets the width of the block before applying margins. This means your +// styled content will exactly equal the size set here. Text will wrap based on +// Padding and Borders set on the style. func (s Style) Width(i int) Style { s.set(widthKey, i) return s @@ -317,6 +375,18 @@ func (s Style) PaddingBottom(i int) Style { return s } +// PaddingChar sets the character used for padding. This is useful for +// rendering blocks with a specific character, such as a space or a dot. +// Example of using [NBSP] as padding to prevent line breaks: +// +// ```go +// s := lipgloss.NewStyle().PaddingChar(lipgloss.NBSP) +// ``` +func (s Style) PaddingChar(r rune) Style { + s.set(paddingCharKey, r) + return s +} + // ColorWhitespace determines whether or not the background color should be // applied to the padding. This is true by default as it's more than likely the // desired and expected behavior, but it can be disabled for certain graphic @@ -382,11 +452,18 @@ func (s Style) MarginBottom(i int) Style { // MarginBackground sets the background color of the margin. Note that this is // also set when inheriting from a style with a background color. In that case // the background color on that style will set the margin color on this style. -func (s Style) MarginBackground(c TerminalColor) Style { +func (s Style) MarginBackground(c color.Color) Style { s.set(marginBackgroundKey, c) return s } +// MarginChar sets the character used for the margin. This is useful for +// rendering blocks with a specific character, such as a space or a dot. +func (s Style) MarginChar(r rune) Style { + s.set(marginCharKey, r) + return s +} + // Border is shorthand for setting the border style and which sides should // have a border at once. The variadic argument sides works as follows: // @@ -487,7 +564,7 @@ func (s Style) BorderLeft(v bool) Style { // top side, followed by the right side, then the bottom, and finally the left. // // With more than four arguments nothing will be set. -func (s Style) BorderForeground(c ...TerminalColor) Style { +func (s Style) BorderForeground(c ...color.Color) Style { if len(c) == 0 { return s } @@ -506,32 +583,80 @@ func (s Style) BorderForeground(c ...TerminalColor) Style { } // BorderTopForeground set the foreground color for the top of the border. -func (s Style) BorderTopForeground(c TerminalColor) Style { +func (s Style) BorderTopForeground(c color.Color) Style { s.set(borderTopForegroundKey, c) return s } // BorderRightForeground sets the foreground color for the right side of the // border. -func (s Style) BorderRightForeground(c TerminalColor) Style { +func (s Style) BorderRightForeground(c color.Color) Style { s.set(borderRightForegroundKey, c) return s } // BorderBottomForeground sets the foreground color for the bottom of the // border. -func (s Style) BorderBottomForeground(c TerminalColor) Style { +func (s Style) BorderBottomForeground(c color.Color) Style { s.set(borderBottomForegroundKey, c) return s } // BorderLeftForeground sets the foreground color for the left side of the // border. -func (s Style) BorderLeftForeground(c TerminalColor) Style { +func (s Style) BorderLeftForeground(c color.Color) Style { s.set(borderLeftForegroundKey, c) return s } +// BorderForegroundBlend sets the foreground colors for the border blend. At least +// 2 colors are required to use blending, otherwise this will no-op with 0 colors, +// and pass to BorderForeground with 1 color. This will override all other border +// foreground colors when used. +// +// When providing colors, in most cases (e.g. when all border sides are enabled), +// you will want to provide a wrapping-set of colors, so the start and end color +// are either the same, or very similar. For example: +// +// lipgloss.NewStyle().BorderForegroundBlend( +// lipgloss.Color("#00FA68"), +// lipgloss.Color("#9900FF"), +// lipgloss.Color("#ED5353"), +// lipgloss.Color("#9900FF"), +// lipgloss.Color("#00FA68"), +// ) +func (s Style) BorderForegroundBlend(c ...color.Color) Style { + if len(c) == 0 { + return s + } + + // Insufficient colors to use blending, pass to BorderForeground. + if len(c) == 1 { + return s.BorderForeground(c...) + } + + s.set(borderForegroundBlendKey, c) + return s +} + +// BorderForegroundBlendOffset sets the border blend offset cells, starting from +// the top left corner. Value can be positive or negative, and does not need to +// equal the dimensions of the border region. Direction (when positive) is as +// follows ("o" is starting point): +// +// o --------> +// ┌──────────┐ +// ^ │ │ | +// | │ │ | +// | │ │ | +// | │ │ v +// └──────────┘ +// <--------- +func (s Style) BorderForegroundBlendOffset(v int) Style { + s.set(borderForegroundBlendOffsetKey, v) + return s +} + // BorderBackground is a shorthand function for setting all of the // background colors of the borders at once. The arguments work as follows: // @@ -547,7 +672,7 @@ func (s Style) BorderLeftForeground(c TerminalColor) Style { // top side, followed by the right side, then the bottom, and finally the left. // // With more than four arguments nothing will be set. -func (s Style) BorderBackground(c ...TerminalColor) Style { +func (s Style) BorderBackground(c ...color.Color) Style { if len(c) == 0 { return s } @@ -566,27 +691,27 @@ func (s Style) BorderBackground(c ...TerminalColor) Style { } // BorderTopBackground sets the background color of the top of the border. -func (s Style) BorderTopBackground(c TerminalColor) Style { +func (s Style) BorderTopBackground(c color.Color) Style { s.set(borderTopBackgroundKey, c) return s } // BorderRightBackground sets the background color of right side the border. -func (s Style) BorderRightBackground(c TerminalColor) Style { +func (s Style) BorderRightBackground(c color.Color) Style { s.set(borderRightBackgroundKey, c) return s } // BorderBottomBackground sets the background color of the bottom of the // border. -func (s Style) BorderBottomBackground(c TerminalColor) Style { +func (s Style) BorderBottomBackground(c color.Color) Style { s.set(borderBottomBackgroundKey, c) return s } // BorderLeftBackground set the background color of the left side of the // border. -func (s Style) BorderLeftBackground(c TerminalColor) Style { +func (s Style) BorderLeftBackground(c color.Color) Style { s.set(borderLeftBackgroundKey, c) return s } @@ -685,10 +810,18 @@ func (s Style) Transform(fn func(string) string) Style { return s } -// Renderer sets the renderer for the style. This is useful for changing the -// renderer for a style that is being used in a different context. -func (s Style) Renderer(r *Renderer) Style { - s.r = r +// Hyperlink sets a hyperlink on a style. This is useful for rendering text that +// can be clicked on in a terminal emulator that supports hyperlinks. +// +// Example: +// +// s := lipgloss.NewStyle().Hyperlink("https://charm.sh") +// s := lipgloss.NewStyle().Hyperlink("https://charm.sh", "id=1") +func (s Style) Hyperlink(link string, params ...string) Style { + s.set(linkKey, link) + if len(params) > 0 { + s.set(linkParamsKey, strings.Join(params, ":")) + } return s } @@ -768,7 +901,7 @@ func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) { // whichSidesColor is like whichSides, except it operates on a series of // boolean values. See the comment on whichSidesInt for details on how this // works. -func whichSidesColor(i ...TerminalColor) (top, right, bottom, left TerminalColor, ok bool) { +func whichSidesColor(i ...color.Color) (top, right, bottom, left color.Color, ok bool) { switch len(i) { case 1: top = i[0] diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/size.go b/tools/vendor/charm.land/lipgloss/v2/size.go similarity index 75% rename from tools/vendor/github.com/charmbracelet/lipgloss/size.go rename to tools/vendor/charm.land/lipgloss/v2/size.go index e169ff5e2..e0384d035 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/size.go +++ b/tools/vendor/charm.land/lipgloss/v2/size.go @@ -10,10 +10,10 @@ import ( // ignored and characters wider than one cell (such as Chinese characters and // emojis) are appropriately measured. // -// You should use this instead of len(string) len([]rune(string) as neither +// You should use this instead of len(string) or len([]rune(string) as neither // will give you accurate results. func Width(str string) (width int) { - for _, l := range strings.Split(str, "\n") { + for l := range strings.SplitSeq(str, "\n") { w := ansi.StringWidth(l) if w > width { width = w @@ -24,9 +24,8 @@ func Width(str string) (width int) { } // Height returns height of a string in cells. This is done simply by -// counting \n characters. If your strings use \r\n for newlines you should -// convert them to \n first, or simply write a separate function for measuring -// height. +// counting \n characters. If your output has \r\n, that sequence will be +// replaced with a \n in [Style.Render]. func Height(str string) int { return strings.Count(str, "\n") + 1 } diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/style.go b/tools/vendor/charm.land/lipgloss/v2/style.go similarity index 68% rename from tools/vendor/github.com/charmbracelet/lipgloss/style.go rename to tools/vendor/charm.land/lipgloss/v2/style.go index 59fa3ab21..3cd659526 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/style.go +++ b/tools/vendor/charm.land/lipgloss/v2/style.go @@ -1,15 +1,18 @@ package lipgloss import ( + "image/color" "strings" "unicode" "github.com/charmbracelet/x/ansi" - "github.com/charmbracelet/x/cellbuf" - "github.com/muesli/termenv" ) -const tabWidthDefault = 4 +const ( + // NBSP is the non-breaking space rune. + NBSP = '\u00A0' + tabWidthDefault = 4 +) // Property for a key. type propKey int64 @@ -19,7 +22,6 @@ const ( // Boolean props come first. boldKey propKey = 1 << iota italicKey - underlineKey strikethroughKey reverseKey blinkKey @@ -29,8 +31,10 @@ const ( colorWhitespaceKey // Non-boolean props. + underlineKey foregroundKey backgroundKey + underlineColorKey widthKey heightKey alignHorizontalKey @@ -41,6 +45,7 @@ const ( paddingRightKey paddingBottomKey paddingLeftKey + paddingCharKey // Margins. marginTopKey @@ -48,6 +53,7 @@ const ( marginBottomKey marginLeftKey marginBackgroundKey + marginCharKey // Border runes. borderStyleKey @@ -63,6 +69,8 @@ const ( borderRightForegroundKey borderBottomForegroundKey borderLeftForegroundKey + borderForegroundBlendKey + borderForegroundBlendOffsetKey // Border background colors. borderTopBackgroundKey @@ -76,6 +84,10 @@ const ( tabWidthKey transformKey + + // Hyperlink. + linkKey + linkParamsKey ) // props is a set of properties. @@ -96,35 +108,53 @@ func (p props) has(k propKey) bool { return p&props(k) != 0 } -// NewStyle returns a new, empty Style. While it's syntactic sugar for the -// Style{} primitive, it's recommended to use this function for creating styles -// in case the underlying implementation changes. It takes an optional string -// value to be set as the underlying string value for this style. -func NewStyle() Style { - return renderer.NewStyle() -} +// Underline is the style of the underline. +// +// Caveats: +// - Not all terminals support all underline styles. +// - Some terminals may render unsupported styles as standard underlines. +// - Terminal themes may affect the visibility of different underline styles. +type Underline = ansi.Underline + +const ( + // UnderlineNone is no underline. + UnderlineNone = ansi.UnderlineNone + // UnderlineSingle is a single underline. This is the default when underline is enabled. + UnderlineSingle = ansi.UnderlineSingle + // UnderlineDouble is a double underline. + UnderlineDouble = ansi.UnderlineDouble + // UnderlineCurly is a curly underline. + UnderlineCurly = ansi.UnderlineCurly + // UnderlineDotted is a dotted underline. + UnderlineDotted = ansi.UnderlineDotted + // UnderlineDashed is a dashed underline. + UnderlineDashed = ansi.UnderlineDashed +) // NewStyle returns a new, empty Style. While it's syntactic sugar for the -// Style{} primitive, it's recommended to use this function for creating styles -// in case the underlying implementation changes. It takes an optional string -// value to be set as the underlying string value for this style. -func (r *Renderer) NewStyle() Style { - s := Style{r: r} - return s +// [Style]{} primitive, it's recommended to use this function for creating styles +// in case the underlying implementation changes. +func NewStyle() Style { + return Style{} } // Style contains a set of rules that comprise a style as a whole. type Style struct { - r *Renderer props props value string + // hyperlink + link, linkParams string + // we store bool props values here attrs int // props that have values - fgColor TerminalColor - bgColor TerminalColor + fgColor color.Color + bgColor color.Color + ulColor color.Color + + ul Underline width int height int @@ -136,22 +166,26 @@ type Style struct { paddingRight int paddingBottom int paddingLeft int + paddingChar rune marginTop int marginRight int marginBottom int marginLeft int - marginBgColor TerminalColor - - borderStyle Border - borderTopFgColor TerminalColor - borderRightFgColor TerminalColor - borderBottomFgColor TerminalColor - borderLeftFgColor TerminalColor - borderTopBgColor TerminalColor - borderRightBgColor TerminalColor - borderBottomBgColor TerminalColor - borderLeftBgColor TerminalColor + marginBgColor color.Color + marginChar rune + + borderStyle Border + borderTopFgColor color.Color + borderRightFgColor color.Color + borderBottomFgColor color.Color + borderLeftFgColor color.Color + borderBlendFgColor []color.Color + borderForegroundBlendOffset int + borderTopBgColor color.Color + borderRightBgColor color.Color + borderBottomBgColor color.Color + borderLeftBgColor color.Color maxWidth int maxHeight int @@ -167,10 +201,10 @@ func joinString(strs ...string) string { } // SetString sets the underlying string value for this style. To render once -// the underlying string is set, use the Style.String. This method is +// the underlying string is set, use the [Style.String]. This method is // a convenience for cases when having a stringer implementation is handy, such // as when using fmt.Sprintf. You can also simply define a style and render out -// strings directly with Style.Render. +// strings directly with [Style.Render]. func (s Style) SetString(strs ...string) Style { s.value = joinString(strs...) return s @@ -232,9 +266,6 @@ func (s Style) Inherit(i Style) Style { // Render applies the defined style formatting to a given string. func (s Style) Render(strs ...string) string { - if s.r == nil { - s.r = renderer - } if s.value != "" { strs = append([]string{s.value}, strs...) } @@ -242,14 +273,12 @@ func (s Style) Render(strs ...string) string { var ( str = joinString(strs...) - p = s.r.ColorProfile() - te = p.String() - teSpace = p.String() - teWhitespace = p.String() + te ansi.Style + teSpace ansi.Style + teWhitespace ansi.Style bold = s.getAsBool(boldKey, false) italic = s.getAsBool(italicKey, false) - underline = s.getAsBool(underlineKey, false) strikethrough = s.getAsBool(strikethroughKey, false) reverse = s.getAsBool(reverseKey, false) blink = s.getAsBool(blinkKey, false) @@ -257,7 +286,9 @@ func (s Style) Render(strs ...string) string { fg = s.getAsColor(foregroundKey) bg = s.getAsColor(backgroundKey) + ul = s.getAsColor(underlineColorKey) + underline = s.ul != UnderlineNone width = s.getAsInt(widthKey) height = s.getAsInt(heightKey) horizontalAlign = s.getAsPosition(alignHorizontalKey) @@ -268,6 +299,9 @@ func (s Style) Render(strs ...string) string { bottomPadding = s.getAsInt(paddingBottomKey) leftPadding = s.getAsInt(paddingLeftKey) + horizontalBorderSize = s.GetHorizontalBorderSize() + verticalBorderSize = s.GetVerticalBorderSize() + colorWhitespace = s.getAsBool(colorWhitespaceKey, true) inline = s.getAsBool(inlineKey, false) maxWidth = s.getAsInt(maxWidthKey) @@ -284,6 +318,8 @@ func (s Style) Render(strs ...string) string { useSpaceStyler = (underline && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underlineSpaces || strikethroughSpaces transform = s.getAsTransform(transformKey) + + link, linkParams = s.GetHyperlink() ) if transform != nil { @@ -294,62 +330,68 @@ func (s Style) Render(strs ...string) string { return s.maybeConvertTabs(str) } - // Enable support for ANSI on the legacy Windows cmd.exe console. This is a - // no-op on non-Windows systems and on Windows runs only once. - enableLegacyWindowsANSI() - if bold { te = te.Bold() } if italic { - te = te.Italic() + te = te.Italic(true) } if underline { - te = te.Underline() + te = te.Underline(true) } if reverse { - teWhitespace = teWhitespace.Reverse() - te = te.Reverse() + teWhitespace = teWhitespace.Reverse(true) + te = te.Reverse(true) } if blink { - te = te.Blink() + te = te.Blink(true) } if faint { te = te.Faint() } if fg != noColor { - te = te.Foreground(fg.color(s.r)) + te = te.ForegroundColor(fg) if styleWhitespace { - teWhitespace = teWhitespace.Foreground(fg.color(s.r)) + teWhitespace = teWhitespace.ForegroundColor(fg) } if useSpaceStyler { - teSpace = teSpace.Foreground(fg.color(s.r)) + teSpace = teSpace.ForegroundColor(fg) } } if bg != noColor { - te = te.Background(bg.color(s.r)) + te = te.BackgroundColor(bg) + if colorWhitespace { + teWhitespace = teWhitespace.BackgroundColor(bg) + } + if useSpaceStyler { + teSpace = teSpace.BackgroundColor(bg) + } + } + + if ul != noColor { + te = te.UnderlineColor(ul) if colorWhitespace { - teWhitespace = teWhitespace.Background(bg.color(s.r)) + teWhitespace = teWhitespace.UnderlineColor(ul) } if useSpaceStyler { - teSpace = teSpace.Background(bg.color(s.r)) + teSpace = teSpace.UnderlineColor(ul) } } if underline { - te = te.Underline() + te = te.UnderlineStyle(s.ul) } if strikethrough { - te = te.CrossOut() + te = te.Strikethrough(true) } if underlineSpaces { - teSpace = teSpace.Underline() + teSpace = teSpace.Underline(true) } if strikethroughSpaces { - teSpace = teSpace.CrossOut() + teSpace = teSpace.Strikethrough(true) } // Potentially convert tabs to spaces @@ -362,21 +404,30 @@ func (s Style) Render(strs ...string) string { str = strings.ReplaceAll(str, "\n", "") } + // Include borders in block size. + width -= horizontalBorderSize + height -= verticalBorderSize + // Word wrap if !inline && width > 0 { wrapAt := width - leftPadding - rightPadding - str = cellbuf.Wrap(str, wrapAt, "") + str = Wrap(str, wrapAt, "") } // Render core text { var b strings.Builder - l := strings.Split(str, "\n") - for i := range l { + isFirst := true + for line := range strings.SplitSeq(str, "\n") { + if isFirst { + isFirst = false + } else { + b.WriteRune('\n') + } if useSpaceStyler { // Look for spaces and apply a different styler - for _, r := range l[i] { + for _, r := range line { if unicode.IsSpace(r) { b.WriteString(teSpace.Styled(string(r))) continue @@ -384,32 +435,37 @@ func (s Style) Render(strs ...string) string { b.WriteString(te.Styled(string(r))) } } else { - b.WriteString(te.Styled(l[i])) - } - if i != len(l)-1 { - b.WriteRune('\n') + b.WriteString(te.Styled(line)) } } str = b.String() + + if len(link) > 0 { + str = ansi.SetHyperlink(link, linkParams) + str + ansi.ResetHyperlink() + } } // Padding if !inline { //nolint:nestif + padChar := s.paddingChar + if padChar == 0 { + padChar = ' ' + } if leftPadding > 0 { - var st *termenv.Style + var st *ansi.Style if colorWhitespace || styleWhitespace { st = &teWhitespace } - str = padLeft(str, leftPadding, st) + str = padLeft(str, leftPadding, st, padChar) } if rightPadding > 0 { - var st *termenv.Style + var st *ansi.Style if colorWhitespace || styleWhitespace { st = &teWhitespace } - str = padRight(str, rightPadding, st) + str = padRight(str, rightPadding, st, padChar) } if topPadding > 0 { @@ -433,7 +489,7 @@ func (s Style) Render(strs ...string) string { numLines := strings.Count(str, "\n") if numLines != 0 || width != 0 { - var st *termenv.Style + var st *ansi.Style if colorWhitespace || styleWhitespace { st = &teWhitespace } @@ -491,17 +547,21 @@ func (s Style) applyMargins(str string, inline bool) string { bottomMargin = s.getAsInt(marginBottomKey) leftMargin = s.getAsInt(marginLeftKey) - styler termenv.Style + style ansi.Style ) bgc := s.getAsColor(marginBackgroundKey) if bgc != noColor { - styler = styler.Background(bgc.color(s.r)) + style = style.BackgroundColor(bgc) } // Add left and right margin - str = padLeft(str, leftMargin, &styler) - str = padRight(str, rightMargin, &styler) + marginChar := s.marginChar + if marginChar == 0 { + marginChar = ' ' + } + str = padLeft(str, leftMargin, &style, marginChar) + str = padRight(str, rightMargin, &style, marginChar) // Top/bottom margin if !inline { @@ -509,10 +569,10 @@ func (s Style) applyMargins(str string, inline bool) string { spaces := strings.Repeat(" ", width) if topMargin > 0 { - str = styler.Styled(strings.Repeat(spaces+"\n", topMargin)) + str + str = style.Styled(strings.Repeat(spaces+"\n", topMargin)) + str } if bottomMargin > 0 { - str += styler.Styled(strings.Repeat("\n"+spaces, bottomMargin)) + str += style.Styled(strings.Repeat("\n"+spaces, bottomMargin)) } } @@ -520,65 +580,54 @@ func (s Style) applyMargins(str string, inline bool) string { } // Apply left padding. -func padLeft(str string, n int, style *termenv.Style) string { - return pad(str, -n, style) +func padLeft(str string, n int, style *ansi.Style, r rune) string { + return pad(str, -n, style, r) } // Apply right padding. -func padRight(str string, n int, style *termenv.Style) string { - return pad(str, n, style) +func padRight(str string, n int, style *ansi.Style, r rune) string { + return pad(str, n, style, r) } // pad adds padding to either the left or right side of a string. // Positive values add to the right side while negative values // add to the left side. -func pad(str string, n int, style *termenv.Style) string { +// r is the rune to use for padding. We use " " for margins and +// "\u00A0" for padding so that the padding is preserved when the +// string is copied and pasted. +func pad(str string, n int, style *ansi.Style, r rune) string { if n == 0 { return str } - sp := strings.Repeat(" ", abs(n)) + sp := strings.Repeat(string(r), abs(n)) if style != nil { sp = style.Styled(sp) } b := strings.Builder{} - l := strings.Split(str, "\n") - - for i := range l { + isFirst := true + for line := range strings.SplitSeq(str, "\n") { + if isFirst { + isFirst = false + } else { + b.WriteRune('\n') + } switch { // pad right case n > 0: - b.WriteString(l[i]) + b.WriteString(line) b.WriteString(sp) // pad left default: b.WriteString(sp) - b.WriteString(l[i]) - } - - if i != len(l)-1 { - b.WriteRune('\n') + b.WriteString(line) } } return b.String() } -func max(a, b int) int { //nolint:unparam,predeclared - if a > b { - return a - } - return b -} - -func min(a, b int) int { //nolint:predeclared - if a < b { - return a - } - return b -} - func abs(a int) int { if a < 0 { return -a diff --git a/tools/vendor/charm.land/lipgloss/v2/terminal.go b/tools/vendor/charm.land/lipgloss/v2/terminal.go new file mode 100644 index 000000000..a336abc77 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/terminal.go @@ -0,0 +1,124 @@ +package lipgloss + +import ( + "fmt" + "image/color" + "io" + "strings" + "time" + + uv "github.com/charmbracelet/ultraviolet" + "github.com/charmbracelet/x/ansi" +) + +// queryBackgroundColor queries the terminal for the background color. +// If the terminal does not support querying the background color, nil is +// returned. +// +// Note: you will need to set the input to raw mode before calling this +// function. +// +// state, _ := term.MakeRaw(in.Fd()) +// defer term.Restore(in.Fd(), state) +// +// copied from x/term@v0.1.3. +func queryBackgroundColor(in io.Reader, out io.Writer) (c color.Color, err error) { + err = queryTerminal(in, out, defaultQueryTimeout, + func(seq string, pa *ansi.Parser) bool { + switch { + case ansi.HasOscPrefix(seq): + switch pa.Command() { + case 11: // OSC 11 + parts := strings.Split(string(pa.Data()), ";") + if len(parts) != 2 { + break // invalid, but we still need to parse the next sequence + } + c = ansi.XParseColor(parts[1]) + } + case ansi.HasCsiPrefix(seq): + switch pa.Command() { + case ansi.Command('?', 0, 'c'): // DA1 + return false + } + } + return true + }, ansi.RequestBackgroundColor+ansi.RequestPrimaryDeviceAttributes) + return +} + +const defaultQueryTimeout = time.Second * 2 + +// queryTerminalFilter is a function that filters input events using a type +// switch. If false is returned, the QueryTerminal function will stop reading +// input. +type queryTerminalFilter func(seq string, pa *ansi.Parser) bool + +// queryTerminal queries the terminal for support of various features and +// returns a list of response events. +// Most of the time, you will need to set stdin to raw mode before calling this +// function. +// Note: This function will block until the terminal responds or the timeout +// is reached. +// copied from x/term@v0.1.3. +func queryTerminal( + in io.Reader, + out io.Writer, + timeout time.Duration, + filter queryTerminalFilter, + query string, +) error { + // We use [uv.NewCancelReader] because it uses a different Windows + // implementation than the on in the [cancelreader] library, which uses + // the Cancel IO API to cancel reads instead of using Overlapped IO. + rd, err := uv.NewCancelReader(in) + if err != nil { + return fmt.Errorf("could not create cancel reader: %w", err) + } + + defer rd.Close() //nolint: errcheck + + done := make(chan struct{}, 1) + defer close(done) + go func() { + select { + case <-done: + case <-time.After(timeout): + rd.Cancel() + } + }() + + if _, err := io.WriteString(out, query); err != nil { + return fmt.Errorf("could not write query: %w", err) + } + + pa := ansi.GetParser() + defer ansi.PutParser(pa) + + var acc []byte // Accumulate partial responses before filtering + var buf [256]byte // 256 bytes should be enough for most responses + var state byte + for { + n, err := rd.Read(buf[:]) + if err != nil { + return fmt.Errorf("could not read from input: %w", err) + } + + p := buf[:] + for n > 0 { + seq, _, read, newState := ansi.DecodeSequence(p[:n], state, pa) + acc = append(acc, seq...) + + if newState == ansi.NormalState { + if !filter(string(acc), pa) { + return nil + } + + acc = acc[:0] + } + + state = newState + n -= read + p = p[read:] + } + } +} diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/unset.go b/tools/vendor/charm.land/lipgloss/v2/unset.go similarity index 91% rename from tools/vendor/github.com/charmbracelet/lipgloss/unset.go rename to tools/vendor/charm.land/lipgloss/v2/unset.go index 1086e7226..b81ee882a 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/unset.go +++ b/tools/vendor/charm.land/lipgloss/v2/unset.go @@ -19,8 +19,7 @@ func (s Style) UnsetItalic() Style { // UnsetUnderline removes the underline style rule, if set. func (s Style) UnsetUnderline() Style { - s.unset(underlineKey) - return s + return s.Underline(false) } // UnsetStrikethrough removes the strikethrough style rule, if set. @@ -96,6 +95,13 @@ func (s Style) UnsetPadding() Style { s.unset(paddingRightKey) s.unset(paddingTopKey) s.unset(paddingBottomKey) + s.unset(paddingCharKey) + return s +} + +// UnsetPaddingChar removes the padding character style rule, if set. +func (s Style) UnsetPaddingChar() Style { + s.unset(paddingCharKey) return s } @@ -237,6 +243,20 @@ func (s Style) UnsetBorderLeftForeground() Style { return s } +// UnsetBorderForegroundBlend removes the border blend foreground color rules, +// if set. +func (s Style) UnsetBorderForegroundBlend() Style { + s.unset(borderForegroundBlendKey) + return s +} + +// UnsetBorderForegroundBlendOffset removes the border blend offset style rule, +// if set. +func (s Style) UnsetBorderForegroundBlendOffset() Style { + s.unset(borderForegroundBlendOffsetKey) + return s +} + // UnsetBorderBackground removes all border background color styles, if // set. func (s Style) UnsetBorderBackground() Style { @@ -324,6 +344,14 @@ func (s Style) UnsetTransform() Style { return s } +// UnsetHyperlink removes the value set by Hyperlink. +func (s Style) UnsetHyperlink() Style { + s.unset(linkKey) + s.unset(linkParamsKey) + s.link, s.linkParams = "", "" // save memory + return s +} + // UnsetString sets the underlying string value to the empty string. func (s Style) UnsetString() Style { s.value = "" diff --git a/tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go b/tools/vendor/charm.land/lipgloss/v2/whitespace.go similarity index 55% rename from tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go rename to tools/vendor/charm.land/lipgloss/v2/whitespace.go index 040dc98e6..e353a076b 100644 --- a/tools/vendor/github.com/charmbracelet/lipgloss/whitespace.go +++ b/tools/vendor/charm.land/lipgloss/v2/whitespace.go @@ -4,24 +4,17 @@ import ( "strings" "github.com/charmbracelet/x/ansi" - "github.com/muesli/termenv" ) // whitespace is a whitespace renderer. type whitespace struct { - re *Renderer - style termenv.Style chars string + style Style } -// newWhitespace creates a new whitespace renderer. The order of the options -// matters, if you're using WithWhitespaceRenderer, make sure it comes first as -// other options might depend on it. -func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace { - w := &whitespace{ - re: r, - style: r.ColorProfile().String(), - } +// newWhitespace creates a new whitespace renderer. +func newWhitespace(opts ...WhitespaceOption) *whitespace { + w := &whitespace{} for _, opt := range opts { opt(w) } @@ -41,11 +34,18 @@ func (w whitespace) render(width int) string { // Cycle through runes and print them into the whitespace. for i := 0; i < width; { b.WriteRune(r[j]) + // Measure the width of the rune we just wrote, ensuring we always + // make progress to avoid infinite loops with zero-width characters + // like tabs. + runeWidth := ansi.StringWidth(string(r[j])) + if runeWidth < 1 { + runeWidth = 1 + } + i += runeWidth j++ if j >= len(r) { j = 0 } - i += ansi.StringWidth(string(r[j])) } // Fill any extra gaps white spaces. This might be necessary if any runes @@ -55,23 +55,16 @@ func (w whitespace) render(width int) string { b.WriteString(strings.Repeat(" ", short)) } - return w.style.Styled(b.String()) + return w.style.Render(b.String()) } // WhitespaceOption sets a styling rule for rendering whitespace. type WhitespaceOption func(*whitespace) -// WithWhitespaceForeground sets the color of the characters in the whitespace. -func WithWhitespaceForeground(c TerminalColor) WhitespaceOption { - return func(w *whitespace) { - w.style = w.style.Foreground(c.color(w.re)) - } -} - -// WithWhitespaceBackground sets the background color of the whitespace. -func WithWhitespaceBackground(c TerminalColor) WhitespaceOption { +// WithWhitespaceStyle sets the style for the whitespace. +func WithWhitespaceStyle(s Style) WhitespaceOption { return func(w *whitespace) { - w.style = w.style.Background(c.color(w.re)) + w.style = s } } diff --git a/tools/vendor/charm.land/lipgloss/v2/wrap.go b/tools/vendor/charm.land/lipgloss/v2/wrap.go new file mode 100644 index 000000000..ca0a1e239 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/wrap.go @@ -0,0 +1,107 @@ +package lipgloss + +import ( + "bytes" + "io" + + uv "github.com/charmbracelet/ultraviolet" + "github.com/charmbracelet/x/ansi" +) + +// Wrap wraps the given string to the given width, preserving ANSI styles and links. +func Wrap(s string, width int, breakpoints string) string { + var buf bytes.Buffer + s = ansi.Wrap(s, width, breakpoints) + w := NewWrapWriter(&buf) + defer w.Close() //nolint:errcheck + _, _ = io.WriteString(w, s) + return buf.String() +} + +// WrapWriter 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. +// +// When it encounters a newline, it resets the style and link, writes the +// newline, and then reapplies the style and link to the next line. +type WrapWriter struct { + w io.Writer + p *ansi.Parser + style uv.Style + link uv.Link +} + +// NewWrapWriter returns a new [WrapWriter]. +func NewWrapWriter(w io.Writer) *WrapWriter { + pw := &WrapWriter{w: w} + pw.p = ansi.GetParser() + handleCsi := func(cmd ansi.Cmd, params ansi.Params) { + if cmd == 'm' { + uv.ReadStyle(params, &pw.style) + } + } + handleOsc := func(cmd int, data []byte) { + if cmd == 8 { + uv.ReadLink(data, &pw.link) + } + } + pw.p.SetHandler(ansi.Handler{ + HandleCsi: handleCsi, + HandleOsc: handleOsc, + }) + return pw +} + +// Style returns the current pen style. +func (w *WrapWriter) Style() uv.Style { + return w.style +} + +// Link returns the current pen link. +func (w *WrapWriter) Link() uv.Link { + return w.link +} + +// Write writes to the buffer. +func (w *WrapWriter) Write(p []byte) (int, error) { + for i := range p { + b := p[i] + w.p.Advance(b) + if b == '\n' { + if !w.style.IsZero() { + _, _ = w.w.Write([]byte(ansi.ResetStyle)) + } + if !w.link.IsZero() { + _, _ = w.w.Write([]byte(ansi.ResetHyperlink())) + } + } + + _, _ = w.w.Write([]byte{b}) + if b == '\n' { + if !w.link.IsZero() { + _, _ = w.w.Write([]byte(ansi.SetHyperlink(w.link.URL, w.link.Params))) + } + if !w.style.IsZero() { + _, _ = w.w.Write([]byte(w.style.String())) + } + } + } + + 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 *WrapWriter) Close() error { + if !w.style.IsZero() { + _, _ = w.w.Write([]byte(ansi.ResetStyle)) + } + if !w.link.IsZero() { + _, _ = w.w.Write([]byte(ansi.ResetHyperlink())) + } + if w.p != nil { + ansi.PutParser(w.p) + w.p = nil + } + return nil +} diff --git a/tools/vendor/charm.land/lipgloss/v2/writer.go b/tools/vendor/charm.land/lipgloss/v2/writer.go new file mode 100644 index 000000000..78b48b8d3 --- /dev/null +++ b/tools/vendor/charm.land/lipgloss/v2/writer.go @@ -0,0 +1,160 @@ +package lipgloss + +import ( + "bytes" + "fmt" + "io" + "os" + + "github.com/charmbracelet/colorprofile" +) + +// Writer is the default writer that prints to stdout, automatically +// downsampling colors when necessary. +var Writer = colorprofile.NewWriter(os.Stdout, os.Environ()) + +// Println to stdout, automatically downsampling colors when necessary, ending +// with a trailing newline. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("breakfast") +// +// Println("Time for a", str, "sandwich!") +func Println(v ...any) (int, error) { + return fmt.Fprintln(Writer, v...) //nolint:wrapcheck +} + +// Printf prints formatted text to stdout, automatically downsampling colors +// when necessary. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("knuckle") +// +// Printf("Time for a %s sandwich!\n", str) +func Printf(format string, v ...any) (int, error) { + return fmt.Fprintf(Writer, format, v...) //nolint:wrapcheck +} + +// Print to stdout, automatically downsampling colors when necessary. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("Who wants marmalade?\n") +// +// Print(str) +func Print(v ...any) (int, error) { + return fmt.Fprint(Writer, v...) //nolint:wrapcheck +} + +// Fprint pritnts to the given writer, automatically downsampling colors when +// necessary. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("guzzle") +// +// Fprint(os.Stderr, "I %s horchata pretty much all the time.\n", str) +func Fprint(w io.Writer, v ...any) (int, error) { + return fmt.Fprint(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck +} + +// Fprintln prints to the given writer, automatically downsampling colors when +// necessary, and ending with a trailing newline. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("Sandwich time!") +// +// Fprintln(os.Stderr, str) +func Fprintln(w io.Writer, v ...any) (int, error) { + return fmt.Fprintln(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck +} + +// Fprintf prints text to a writer, against the given format, automatically +// downsampling colors when necessary. +// +// Example: +// +// str := NewStyle(). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("artichokes") +// +// Fprintf(os.Stderr, "I really love %s!\n", food) +func Fprintf(w io.Writer, format string, v ...any) (int, error) { + return fmt.Fprintf(colorprofile.NewWriter(w, os.Environ()), format, v...) //nolint:wrapcheck +} + +// Sprint returns a string for stdout, automatically downsampling colors when +// necessary. +// +// Example: +// +// str := NewStyle(). +// Faint(true). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("I love to eat") +// +// str = Sprint(str) +func Sprint(v ...any) string { + var buf bytes.Buffer + w := colorprofile.Writer{ + Forward: &buf, + Profile: Writer.Profile, + } + fmt.Fprint(&w, v...) //nolint:errcheck + return buf.String() +} + +// Sprintln returns a string for stdout, automatically downsampling colors when +// necessary, and ending with a trailing newline. +// +// Example: +// +// str := NewStyle(). +// Bold(true). +// Foreground(lipgloss.Color("#6a00ff")). +// Render("Yummy!") +// +// str = Sprintln(str) +func Sprintln(v ...any) string { + var buf bytes.Buffer + w := colorprofile.Writer{ + Forward: &buf, + Profile: Writer.Profile, + } + fmt.Fprintln(&w, v...) //nolint:errcheck + return buf.String() +} + +// Sprintf returns a formatted string for stdout, automatically downsampling +// colors when necessary. +// +// Example: +// +// str := NewStyle(). +// Bold(true). +// Foreground(lipgloss.Color("#fccaee")). +// Render("Cantaloupe") +// +// str = Sprintf("I really love %s!", str) +func Sprintf(format string, v ...any) string { + var buf bytes.Buffer + w := colorprofile.Writer{ + Forward: &buf, + Profile: Writer.Profile, + } + fmt.Fprintf(&w, format, v...) //nolint:errcheck + return buf.String() +} diff --git a/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE new file mode 100644 index 000000000..a7e77cb28 --- /dev/null +++ b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go new file mode 100644 index 000000000..68d130989 --- /dev/null +++ b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go @@ -0,0 +1,33 @@ +package util + +import ( + "go/ast" + "go/types" + + "golang.org/x/tools/go/analysis" +) + +// IsChObj returns true if the input ast.Expr is of type clickhouse go driver +func IsChObj(pass *analysis.Pass, expr ast.Expr, name string) bool { + t := pass.TypesInfo.TypeOf(expr) + if t == nil { + return false + } + named, ok := t.(*types.Named) + if !ok { + return false + } + obj := named.Obj() + if obj.Pkg() == nil { + return false + } + return obj.Pkg().Path() == "github.com/ClickHouse/clickhouse-go/v2/lib/driver" && + obj.Name() == name +} + +func IdentName(expr ast.Expr) string { + if id, ok := expr.(*ast.Ident); ok { + return id.Name + } + return "" +} diff --git a/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go new file mode 100644 index 000000000..3da2c55d6 --- /dev/null +++ b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go @@ -0,0 +1,182 @@ +package chbatchclose + +import ( + "go/ast" + "go/token" + "os" + "strconv" + + "github.com/ClickHouse/clickhouse-go-linter/internal/util" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +type analyzer struct { + // if true, report valid usages and log spurious but valid cases. + debug bool +} + +func NewAnalyzer() *analysis.Analyzer { + debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG")) + a := analyzer{ + debug: debug, + } + return &analysis.Analyzer{ + Name: "chbatchclosecheck", + Doc: "chbatchclosecheck checks whether defer batch.Close() is called on ClickHouse driver Batch variables", + Run: a.run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +func (a *analyzer) run(pass *analysis.Pass) (any, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + nodeFilter := []ast.Node{ + (*ast.FuncDecl)(nil), + (*ast.FuncLit)(nil), + } + + insp.Preorder(nodeFilter, func(n ast.Node) { + var body *ast.BlockStmt + switch fn := n.(type) { + case *ast.FuncDecl: + body = fn.Body + case *ast.FuncLit: + body = fn.Body + } + + if body == nil { + return + } + a.checkFunc(pass, body) + }) + + return nil, nil +} + +// batchUsage tracks whether a driver.Batch variable has a defer Close/Abort or is returned. +type batchUsage struct { + assignPos token.Pos + deferredClose bool + returned bool +} + +func (b *batchUsage) report(varName string, pass *analysis.Pass, debug bool) { + if b.assignPos == token.NoPos { + // no usage of Batch + return + } + if !b.deferredClose && !b.returned { + pass.Reportf(b.assignPos, + "clickhouse Batch %s must be closed defensively with defer %s.Close() after successful instantiation", + varName, varName) + } else if debug { + if b.deferredClose { + pass.Reportf(b.assignPos, + "clickhouse Batch %s is properly closed defensively after successful instantiation [valid]", + varName) + } else { + pass.Reportf(b.assignPos, + "clickhouse Batch %s is returned by the function [valid]", + varName) + } + } +} + +// checkFunc analyzes a single function/closure body. +// It does a single-pass collection of Batch assignments, defer Close/Abort calls, and return statements. +// It does not descend into nested closures (they are handled as separate units by the Preorder visitor above). +func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) { + usages := map[string]*batchUsage{} + + ast.Inspect(body, func(n ast.Node) bool { + if n == nil { + return false + } + // don't descend into nested closures + if n != body { + if _, ok := n.(*ast.FuncLit); ok { + return false + } + } + + switch node := n.(type) { + case *ast.AssignStmt: + a.handleAssign(pass, node, usages) + case *ast.DeferStmt: + handleDefer(node, usages) + case *ast.ReturnStmt: + handleReturn(node, usages) + } + + return true + }) + + // remaining usages that were not flushed + for varName, u := range usages { + u.report(varName, pass, a.debug) + } +} + +// handleAssign checks if any LHS variable in the assignment is of type driver.Batch. +// If a tracked variable is reassigned, it flushes/reports the previous tracking first. +func (a *analyzer) handleAssign(pass *analysis.Pass, assign *ast.AssignStmt, usages map[string]*batchUsage) { + for _, lhs := range assign.Lhs { + name := util.IdentName(lhs) + if name == "" { + continue + } + if name == "_" && util.IsChObj(pass, lhs, "Batch") { + pass.Reportf(assign.Pos(), "clickhouse Batch assigned to blank identifier. Connection leak. clickhouse Batch must be instantiated and closed defensively with defer batch.Close() after successful instantiation") + continue + } + + // if this var was already tracked, flush previous usage before re-tracking + if u, ok := usages[name]; ok { + u.report(name, pass, a.debug) + delete(usages, name) + } + + if util.IsChObj(pass, lhs, "Batch") { + usages[name] = &batchUsage{assignPos: assign.Pos()} + } + } +} + +// handleDefer checks if a defer statement calls Close() or Abort() on a tracked Batch variable. +func handleDefer(deferStmt *ast.DeferStmt, usages map[string]*batchUsage) { + call := deferStmt.Call + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return + } + varName := util.IdentName(sel.X) + if varName == "" { + return + } + u, exists := usages[varName] + if !exists { + return + } + + switch sel.Sel.Name { + case "Close": + u.deferredClose = true + } +} + +// handleReturn checks if any return value is a tracked Batch variable. +func handleReturn(ret *ast.ReturnStmt, usages map[string]*batchUsage) { + for _, result := range ret.Results { + name := util.IdentName(result) + if name == "" { + continue + } + if u, exists := usages[name]; exists { + u.returned = true + } + } +} diff --git a/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go new file mode 100644 index 000000000..bba0f82ad --- /dev/null +++ b/tools/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go @@ -0,0 +1,162 @@ +package chrowserr + +import ( + "go/ast" + "go/token" + "log" + "os" + "strconv" + + "github.com/ClickHouse/clickhouse-go-linter/internal/util" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +type analyzer struct { + // if true, report valid usages and log spurious but valid cases. + debug bool +} + +func NewAnalyzer() *analysis.Analyzer { + debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG")) + a := analyzer{ + debug: debug, + } + return &analysis.Analyzer{ + Name: "chrowserrcheck", + Doc: "chrowserrcheck checks whether ClickHouse driver Rows.Err is called after Rows.Next()", + Run: a.run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + } +} + +func (a *analyzer) run(pass *analysis.Pass) (any, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + nodeFilter := []ast.Node{ + (*ast.FuncDecl)(nil), + (*ast.FuncLit)(nil), + } + + insp.Preorder(nodeFilter, func(n ast.Node) { + var body *ast.BlockStmt + switch fn := n.(type) { + case *ast.FuncDecl: + body = fn.Body + case *ast.FuncLit: + body = fn.Body + } + + if body == nil { + return + } + a.checkFunc(pass, body) + }) + + return nil, nil +} + +// rowsUsage tracks Next/Err usage observations for a single Rows variable within a function. +type rowsUsage struct { + nextPos token.Pos + errCalled bool +} + +func (r *rowsUsage) report(varName string, pass *analysis.Pass, debug bool) { + if r.nextPos == token.NoPos { + // no usage of rows.Next() + return + } + // rows.Next() was called + if !r.errCalled { + pass.Reportf(r.nextPos, + "clickhouse %s.Err() must be checked after %s.Next()", + varName, varName) + } else if debug { + // for dev purpose - list valid usages + pass.Reportf(r.nextPos, + "clickhouse %s.Err() is properly called after %s.Next() [valid]", + varName, varName) + } +} + +// checkFunc analyzes a single function/closure body. +// It does a single-pass collection of Next() and Err() calls, +// it does not descend into nested closures (they are handled as separate units by the Preorder visitor above). +func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) { + usages := map[string]*rowsUsage{} + ast.Inspect(body, func(n ast.Node) bool { + if n == nil { + return false + } + // don't descend into nested closures + if n != body { + if _, ok := n.(*ast.FuncLit); ok { + return false + } + } + + // if a tracked var appears in an assignment, it means it is re-assigned - run lint report and flush var from usages. + if assign, ok := n.(*ast.AssignStmt); ok { + for _, lhs := range assign.Lhs { + name := util.IdentName(lhs) + if name == "" { + continue + } + if s, ok := usages[name]; ok { + s.report(name, pass, a.debug) + } + delete(usages, name) + } + // let ast.Inspect continue + return true + } + + // handle CH driver method calls Next() and Err() - skip everything else + call, ok := n.(*ast.CallExpr) + if !ok { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + varName := util.IdentName(sel.X) + if varName == "" { + return true + } + if !util.IsChObj(pass, sel.X, "Rows") { + return true + } + + // call is a CH driver Rows method call + switch sel.Sel.Name { + case "Next": + if _, exists := usages[varName]; !exists { + usages[varName] = &rowsUsage{nextPos: call.Pos()} + } else if a.debug { + log.Printf("Rows.Next() is written multiple times with no re-assignment. Valid but rare usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.") + // in particular could be a bug in the re-assignment detection + } + case "Err": + if s, exists := usages[varName]; exists { + s.errCalled = true + s.report(varName, pass, a.debug) + delete(usages, varName) + } else if a.debug { + log.Printf("%s.Err() is called on ClickHouse Rows %s but %s.Next() was never called. Valid but unexpected usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.", + varName, varName, varName) + // in particular could be a bug in the re-assignment detection + } + + } + + return true + }) + + // remaining usages that were not flushed (misusages only, as correct usages are flushed already) + for varName, s := range usages { + s.report(varName, pass, a.debug) + } +} diff --git a/tools/vendor/github.com/Masterminds/semver/v3/.gitignore b/tools/vendor/github.com/Masterminds/semver/v3/.gitignore index 6b061e617..35f0e5a3a 100644 --- a/tools/vendor/github.com/Masterminds/semver/v3/.gitignore +++ b/tools/vendor/github.com/Masterminds/semver/v3/.gitignore @@ -1 +1,2 @@ -_fuzz/ \ No newline at end of file +_fuzz/ +.devcontainer/ \ No newline at end of file diff --git a/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml b/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml index fbc633259..24277f3ac 100644 --- a/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml +++ b/tools/vendor/github.com/Masterminds/semver/v3/.golangci.yml @@ -1,27 +1,42 @@ -run: - deadline: 2m - +version: "2" linters: - disable-all: true + default: none enable: - - misspell - - govet - - staticcheck + - dupl - errcheck - - unparam + - gocyclo + - gosec + - govet - ineffassign + - misspell - nakedret - - gocyclo - - dupl - - goimports - revive - - gosec - - gosimple - - typecheck + - staticcheck + - unparam - unused - -linters-settings: - gofmt: - simplify: true - dupl: - threshold: 600 + settings: + dupl: + threshold: 600 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - goimports + settings: + gofmt: + simplify: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/tools/vendor/github.com/Masterminds/semver/v3/constraints.go b/tools/vendor/github.com/Masterminds/semver/v3/constraints.go index 8b7a10f83..e8353bc46 100644 --- a/tools/vendor/github.com/Masterminds/semver/v3/constraints.go +++ b/tools/vendor/github.com/Masterminds/semver/v3/constraints.go @@ -21,21 +21,43 @@ type Constraints struct { IncludePrerelease bool } +// MaxConstraintLen is the maximum allowed length of a constraint string. +const MaxConstraintLen = 512 + +// MaxConstraintGroups is the maximum number of OR groups allowed in a +// constraint string. +const MaxConstraintGroups = 32 + +// ErrConstraintTooLong is returned when a constraint string exceeds the +// maximum allowed length. +var ErrConstraintTooLong = fmt.Errorf("constraint string is too long (max %d bytes)", MaxConstraintLen) + +// ErrTooManyConstraintGroups is returned when a constraint string contains +// too many OR groups. +var ErrTooManyConstraintGroups = fmt.Errorf("too many constraint groups (max %d)", MaxConstraintGroups) + // NewConstraint returns a Constraints instance that a Version instance can // be checked against. If there is a parse error it will be returned. func NewConstraint(c string) (*Constraints, error) { + if len(c) > MaxConstraintLen { + return nil, ErrConstraintTooLong + } + // Rewrite - ranges into a comparison operation. c = rewriteRange(c) ors := strings.Split(c, "||") + if len(ors) > MaxConstraintGroups { + return nil, ErrTooManyConstraintGroups + } lenors := len(ors) or := make([][]*constraint, lenors) hasPre := make([]bool, lenors) for k, v := range ors { // Validate the segment if !validConstraintRegex.MatchString(v) { - return nil, fmt.Errorf("improper constraint: %s", v) + return nil, fmt.Errorf("improper constraint: %q", v) } cs := findConstraintRegex.FindAllString(v, -1) @@ -104,9 +126,9 @@ func (cs Constraints) Validate(v *Version) (bool, []error) { for _, c := range o { // Before running the check handle the case there the version is // a prerelease and the check is not searching for prereleases. - if !(cs.IncludePrerelease || cs.containsPre[i]) && v.pre != "" { + if !cs.IncludePrerelease && !cs.containsPre[i] && v.pre != "" { if !prerelesase { - em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + em := fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) e = append(e, em) prerelesase = true } @@ -258,7 +280,7 @@ func parseConstraint(c string) (*constraint, error) { if len(c) > 0 { m := constraintRegex.FindStringSubmatch(c) if m == nil { - return nil, fmt.Errorf("improper constraint: %s", c) + return nil, fmt.Errorf("improper constraint: %q", c) } cs := &constraint{ @@ -325,7 +347,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } if c.dirty { @@ -335,7 +357,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error if c.con.Minor() != v.Minor() && !c.minorDirty { return true, nil } else if c.minorDirty { - return false, fmt.Errorf("%s is equal to %s", v, c.orig) + return false, fmt.Errorf("%q is equal to %q", v, c.orig) } else if c.con.Patch() != v.Patch() && !c.patchDirty { return true, nil } else if c.patchDirty { @@ -345,15 +367,15 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error if eq { return true, nil } - return false, fmt.Errorf("%s is equal to %s", v, c.orig) + return false, fmt.Errorf("%q is equal to %q", v, c.orig) } - return false, fmt.Errorf("%s is equal to %s", v, c.orig) + return false, fmt.Errorf("%q is equal to %q", v, c.orig) } } eq := v.Equal(c.con) if eq { - return false, fmt.Errorf("%s is equal to %s", v, c.orig) + return false, fmt.Errorf("%q is equal to %q", v, c.orig) } return true, nil @@ -364,7 +386,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } var eq bool @@ -374,17 +396,17 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er if eq { return true, nil } - return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig) } if v.Major() > c.con.Major() { return true, nil } else if v.Major() < c.con.Major() { - return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig) } else if c.minorDirty { // This is a range case such as >11. When the version is something like // 11.1.0 is it not > 11. For that we would need 12 or higher - return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig) } else if c.patchDirty { // This is for ranges such as >11.1. A version of 11.1.1 is not greater // which one of 11.2.1 is greater @@ -392,7 +414,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er if eq { return true, nil } - return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig) } // If we have gotten here we are not comparing pre-preleases and can use the @@ -401,21 +423,21 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er if eq { return true, nil } - return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig) } func constraintLessThan(v *Version, c *constraint, includePre bool) (bool, error) { // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } eq := v.Compare(c.con) < 0 if eq { return true, nil } - return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig) + return false, fmt.Errorf("%q is greater than or equal to %q", v, c.orig) } func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (bool, error) { @@ -423,21 +445,21 @@ func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (boo // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } eq := v.Compare(c.con) >= 0 if eq { return true, nil } - return false, fmt.Errorf("%s is less than %s", v, c.orig) + return false, fmt.Errorf("%q is less than %q", v, c.orig) } func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool, error) { // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } var eq bool @@ -447,13 +469,13 @@ func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool, if eq { return true, nil } - return false, fmt.Errorf("%s is greater than %s", v, c.orig) + return false, fmt.Errorf("%q is greater than %q", v, c.orig) } if v.Major() > c.con.Major() { - return false, fmt.Errorf("%s is greater than %s", v, c.orig) + return false, fmt.Errorf("%q is greater than %q", v, c.orig) } else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty { - return false, fmt.Errorf("%s is greater than %s", v, c.orig) + return false, fmt.Errorf("%q is greater than %q", v, c.orig) } return true, nil @@ -469,11 +491,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) { // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } if v.LessThan(c.con) { - return false, fmt.Errorf("%s is less than %s", v, c.orig) + return false, fmt.Errorf("%q is less than %q", v, c.orig) } // ~0.0.0 is a special case where all constraints are accepted. It's @@ -484,11 +506,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) { } if v.Major() != c.con.Major() { - return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig) + return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig) } if v.Minor() != c.con.Minor() && !c.minorDirty { - return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig) + return false, fmt.Errorf("%q does not have same major and minor version as %q", v, c.orig) } return true, nil @@ -500,7 +522,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } if c.dirty { @@ -512,7 +534,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e return true, nil } - return false, fmt.Errorf("%s is not equal to %s", v, c.orig) + return false, fmt.Errorf("%q is not equal to %q", v, c.orig) } // ^* --> (any) @@ -528,12 +550,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) { // The existence of prereleases is checked at the group level and passed in. // Exit early if the version has a prerelease but those are to be ignored. if v.Prerelease() != "" && !includePre { - return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) + return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v) } // This less than handles prereleases if v.LessThan(c.con) { - return false, fmt.Errorf("%s is less than %s", v, c.orig) + return false, fmt.Errorf("%q is less than %q", v, c.orig) } var eq bool @@ -548,12 +570,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) { if eq { return true, nil } - return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig) + return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig) } // ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1 if c.con.Major() == 0 && v.Major() > 0 { - return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig) + return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig) } // If the con Minor is > 0 it is not dirty if c.con.Minor() > 0 || c.patchDirty { @@ -561,11 +583,11 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) { if eq { return true, nil } - return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig) + return false, fmt.Errorf("%q does not have same minor version as %q. Expected minor versions to match when constraint major version is 0", v, c.orig) } // ^ when the minor is 0 and minor > 0 is =0.0.z if c.con.Minor() == 0 && v.Minor() > 0 { - return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig) + return false, fmt.Errorf("%q does not have same minor version as %q", v, c.orig) } // At this point the major is 0 and the minor is 0 and not dirty. The patch @@ -574,7 +596,7 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) { if eq { return true, nil } - return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig) + return false, fmt.Errorf("%q does not equal %q. Expect version and constraint to equal when major and minor versions are 0", v, c.orig) } func isX(x string) bool { diff --git a/tools/vendor/github.com/Masterminds/semver/v3/version.go b/tools/vendor/github.com/Masterminds/semver/v3/version.go index 7a3ba7388..da428760c 100644 --- a/tools/vendor/github.com/Masterminds/semver/v3/version.go +++ b/tools/vendor/github.com/Masterminds/semver/v3/version.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "regexp" "strconv" "strings" @@ -48,8 +49,16 @@ var ( // ErrInvalidPrerelease is returned when the pre-release is an invalid format ErrInvalidPrerelease = errors.New("invalid prerelease string") + + // ErrVersionTooLong is returned when a version string exceeds the + // maximum allowed length. + ErrVersionTooLong = fmt.Errorf("version string is too long (max %d bytes)", MaxVersionLen) ) +// MaxVersionLen is the maximum allowed length of a version string. This guards +// against unbounded input causing excessive memory allocations during parsing. +const MaxVersionLen = 256 + // semVerRegex is the regular expression used to parse a semantic version. // This is not the official regex from the semver spec. It has been modified to allow for loose handling // where versions like 2.1 are detected. @@ -94,6 +103,10 @@ func StrictNewVersion(v string) (*Version, error) { return nil, ErrEmptyString } + if len(v) > MaxVersionLen { + return nil, ErrVersionTooLong + } + // Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build parts := strings.SplitN(v, ".", 3) if len(parts) != 3 { @@ -161,6 +174,9 @@ func StrictNewVersion(v string) (*Version, error) { // attempts to convert it to SemVer. If you want to validate it was a strict // semantic version at parse time see StrictNewVersion(). func NewVersion(v string) (*Version, error) { + if len(v) > MaxVersionLen { + return nil, ErrVersionTooLong + } if CoerceNewVersion { return coerceNewVersion(v) } @@ -289,6 +305,8 @@ func coerceNewVersion(v string) (*Version, error) { // New creates a new instance of Version with each of the parts passed in as // arguments instead of parsing a version string. +// Note, New does not validate prerelease or metadata. Incorrect information can +// be passed in. func New(major, minor, patch uint64, pre, metadata string) *Version { v := Version{ major: major, @@ -301,6 +319,7 @@ func New(major, minor, patch uint64, pre, metadata string) *Version { v.original = v.String() + // TODO: In the next semver major version validate the pre and metadata. Return error if there is one. return &v } @@ -388,6 +407,9 @@ func (v Version) IncPatch() Version { } else { vNext.metadata = "" vNext.pre = "" + if v.patch == math.MaxUint64 { + panic("patch version increment would overflow uint64") + } vNext.patch = v.patch + 1 } vNext.original = v.originalVPrefix() + "" + vNext.String() @@ -404,6 +426,9 @@ func (v Version) IncMinor() Version { vNext.metadata = "" vNext.pre = "" vNext.patch = 0 + if v.minor == math.MaxUint64 { + panic("minor version increment would overflow uint64") + } vNext.minor = v.minor + 1 vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext @@ -421,6 +446,9 @@ func (v Version) IncMajor() Version { vNext.pre = "" vNext.patch = 0 vNext.minor = 0 + if v.major == math.MaxUint64 { + panic("major version increment would overflow uint64") + } vNext.major = v.major + 1 vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext @@ -568,7 +596,16 @@ func (v Version) MarshalText() ([]byte, error) { // Scan implements the SQL.Scanner interface. func (v *Version) Scan(value interface{}) error { var s string - s, _ = value.(string) + switch t := value.(type) { + case string: + s = t + case []byte: + s = string(t) + case nil: + return fmt.Errorf("cannot scan nil into Version") + default: + return fmt.Errorf("unsupported Scan type %T", value) + } temp, err := NewVersion(s) if err != nil { return err diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/COPYING b/tools/vendor/github.com/alecthomas/chroma/v2/COPYING index 92dc39f70..33da48981 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/COPYING +++ b/tools/vendor/github.com/alecthomas/chroma/v2/COPYING @@ -17,3 +17,102 @@ 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. + + +// formatters/svg/font_liberation_mono.go + +Digitized data copyright (c) 2010 Google Corporation +with Reserved Font Arimo, Tinos and Cousine. +Copyright (c) 2012 Red Hat, Inc. +with Reserved Font Name Liberation. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile b/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile index c86b37932..8a706766d 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile +++ b/tools/vendor/github.com/alecthomas/chroma/v2/Dockerfile @@ -1,7 +1,7 @@ # Multi-stage Dockerfile for chromad Go application using Hermit-managed tools # Build stage -FROM ubuntu:24.04 AS builder +FROM ubuntu:26.04 AS builder # Install system dependencies RUN apt-get update && apt-get install -y \ diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/README.md b/tools/vendor/github.com/alecthomas/chroma/v2/README.md index 4aeb54d97..d67476958 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/README.md +++ b/tools/vendor/github.com/alecthomas/chroma/v2/README.md @@ -36,25 +36,25 @@ translators for Pygments lexers and styles. | Prefix | Language | :----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk +| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, AMPL, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk | B | Ballerina, Bash, Bash Session, Batchfile, Beef, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck | C | C, C#, C++, C3, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Core, Crystal, CSS, CSV, CUE, Cython | D | D, Dart, Dax, Desktop file, Diff, Django/Jinja, dns, Docker, DTD, Dylan | E | EBNF, Elixir, Elm, EmacsLisp, Erlang | F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp -| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy +| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gettext, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy | H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy | I | Idris, Igor, INI, Io, ISCdhcpd | J | J, Janet, Java, JavaScript, JSON, JSONata, Jsonnet, Julia, Jungle | K | Kakoune, Kotlin -| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua +| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua, Luau | M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonScript, MorrowindScript, Myghty, MySQL | N | NASM, Natural, NDISASM, Newspeak, Nginx configuration file, Nim, Nix, NSIS, Nu | O | Objective-C, ObjectPascal, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode | P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, Promela, PromQL, properties, Protocol Buffer, Protocol Buffer Text Format, PRQL, PSL, Puppet, Python, Python 2 | Q | QBasic, QML | R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, RGBDS Assembly, Ring, RPGLE, RPMSpec, Ruby, Rust -| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog +| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, Spade, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog | T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData, Typst | U | ucode | V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue @@ -226,11 +226,11 @@ formatter outputs raw tokens. The latter is useful for debugging lexers. ### Styles Chroma styles are defined in XML. The style entries use the -[same syntax](http://pygments.org/docs/styles/) as Pygments. - -All Pygments styles have been converted to Chroma using the `_tools/style.py` +[same syntax](http://pygments.org/docs/styles/) as Pygments. All Pygments styles have been converted to Chroma using the `_tools/style.py` script. +Style names are case-insensitive. For example, `monokai` and `Monokai` are treated as the same style. + When you work with one of [Chroma's styles](https://github.com/alecthomas/chroma/tree/master/styles), know that the `Background` token type provides the default style for tokens. It does so by defining a foreground color and background color. diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go b/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go index 70d692ec4..416208a73 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go +++ b/tools/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go @@ -4,7 +4,7 @@ // with Reserved Font Name Liberation. // // This Font Software is licensed under the SIL Open Font License, Version 1.1. -// This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL +// This license is copied below, and is also available with a FAQ at: https://openfontlicense.org // // ----------------------------------------------------------- // SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml new file mode 100644 index 000000000..8c2479e50 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml @@ -0,0 +1,98 @@ + + + AMPL + ampl + *.mod + *.run + text/x-ampl + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml new file mode 100644 index 000000000..e597cd8a9 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml @@ -0,0 +1,37 @@ + + + ERB + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml index 7557bce0f..399cdd008 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml @@ -56,7 +56,7 @@ - + @@ -114,7 +114,7 @@ - + @@ -139,7 +139,7 @@ - + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml new file mode 100644 index 000000000..38c0c21b4 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml @@ -0,0 +1,24 @@ + + + + Gettext + pot + po + *.pot + *.po + application/x-gettext + text/x-gettext + text/gettext + + + + + + + + + + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml index b06227357..b40422f22 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml @@ -76,6 +76,10 @@ + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml index efe80ed37..0e475c53e 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml @@ -133,7 +133,7 @@ - + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml index a34abfa49..0057aa1b6 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml @@ -4,7 +4,9 @@ json *.json *.jsonc + *.json5 *.avsc + .luaurc application/json true true diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml new file mode 100644 index 000000000..cea10eba7 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml @@ -0,0 +1,184 @@ + + + Lateralus + lateralus + ltl + *.ltl + text/x-lateralus + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml index e3d778f12..903d4581f 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml @@ -2,10 +2,8 @@ Lua lua - luau *.lua *.wlua - *.luau text/x-lua application/x-lua diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml new file mode 100644 index 000000000..79a60949a --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml @@ -0,0 +1,173 @@ + + + Luau + luau + *.luau + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml index 7094ddc3e..616d7ae4c 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml @@ -45,7 +45,7 @@ - + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml index 130047df6..fcfbda115 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml @@ -4,6 +4,7 @@ meson meson.build meson.build + meson.options meson_options.txt text/x-meson diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml index b6c2046d5..0517ec8f7 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml @@ -38,7 +38,7 @@ - + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml index c9e22ea57..774bb79be 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml @@ -54,7 +54,7 @@ - + @@ -82,12 +82,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -101,6 +135,10 @@ + + + + @@ -116,7 +154,7 @@ - + @@ -132,6 +170,13 @@ + + + + + + + @@ -161,7 +206,7 @@ - + @@ -170,8 +215,9 @@ - + + @@ -185,7 +231,7 @@ - + @@ -194,7 +240,7 @@ - + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml new file mode 100644 index 000000000..1b3a876ef --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml @@ -0,0 +1,115 @@ + + + scdoc + scdoc + *.scd + *.scdoc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml new file mode 100644 index 000000000..4dfe3292b --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml @@ -0,0 +1,292 @@ + + + Spade + spade + *.spade + text/spade + text/x-spade + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml index a3e3be239..b39c9649c 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml @@ -226,7 +226,7 @@ diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml index 2c6a4d990..99d5d5302 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml @@ -10,6 +10,7 @@ *.wsdl *.wsf *.svg + *.qrc *.csproj *.vcxproj *.fsproj diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go new file mode 100644 index 000000000..2d141ed9e --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go @@ -0,0 +1,29 @@ +package lexers + +import ( + "strings" + + . "github.com/alecthomas/chroma/v2" // nolint +) + +// ERB lexer is Ruby embedded in HTML. +var ERB = Register(DelegatingLexer(HTML, MustNewXMLLexer( + embedded, + "embedded/erb.xml", +).SetConfig( + &Config{ + Name: "ERB", + Aliases: []string{"erb", "html+erb", "html+ruby", "rhtml"}, + Filenames: []string{"*.erb", "*.html.erb", "*.xml.erb", "*.rhtml"}, + MimeTypes: []string{"application/x-ruby-templating"}, + DotAll: true, + }, +).SetAnalyser(func(text string) float32 { + if strings.Contains(text, "<%=") && strings.Contains(text, "%>") { + return 0.4 + } + if strings.Contains(text, "<%") { + return 0.1 + } + return 0.0 +}))) diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go b/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go index c0e5e1081..d183fa5dc 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go +++ b/tools/vendor/github.com/alecthomas/chroma/v2/regexp.go @@ -308,6 +308,7 @@ type RegexLexer struct { rules map[string][]*CompiledRule fetchRulesFunc func() (Rules, error) compileOnce sync.Once + compileError error } func (r *RegexLexer) String() string { @@ -446,8 +447,11 @@ func (r *RegexLexer) needRules() error { var err error if r.fetchRulesFunc != nil { r.compileOnce.Do(func() { - err = r.fetchRules() + r.compileError = r.fetchRules() }) + if r.compileError != nil { + return r.compileError + } } if err := r.maybeCompile(); err != nil { return err diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go b/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go index e26d6f0a5..9e21c8844 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/api.go @@ -4,6 +4,7 @@ import ( "embed" "io/fs" "sort" + "strings" "github.com/alecthomas/chroma/v2" ) @@ -31,7 +32,7 @@ var Registry = func() map[string]*chroma.Style { if err != nil { panic(err) } - registry[style.Name] = style + registry[strings.ToLower(style.Name)] = style _ = r.Close() } return registry @@ -42,7 +43,7 @@ var Fallback = Registry["swapoff"] // Register a chroma.Style. func Register(style *chroma.Style) *chroma.Style { - Registry[style.Name] = style + Registry[strings.ToLower(style.Name)] = style return style } @@ -58,7 +59,7 @@ func Names() []string { // Get named style, or Fallback. func Get(name string) *chroma.Style { - if style, ok := Registry[name]; ok { + if style, ok := Registry[strings.ToLower(name)]; ok { return style } return Fallback diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go b/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go index 4a6aaa665..030985367 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/compat.go @@ -31,6 +31,9 @@ var ( HrDark = Registry["hrdark"] HrHighContrast = Registry["hr_high_contrast"] Igor = Registry["igor"] + KanagawaDragon = Registry["kanagawa-dragon"] + KanagawaLotus = Registry["kanagawa-lotus"] + KanagawaWave = Registry["kanagawa-wave"] Lovelace = Registry["lovelace"] Manni = Registry["manni"] ModusOperandi = Registry["modus-operandi"] diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml new file mode 100644 index 000000000..4c3550623 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml @@ -0,0 +1,83 @@ + \ No newline at end of file diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml index 711aeafc4..c5b0dbb5e 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml @@ -15,6 +15,7 @@ + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml new file mode 100644 index 000000000..114d1651d --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml @@ -0,0 +1,83 @@ + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml new file mode 100644 index 000000000..dde3bc8ef --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml @@ -0,0 +1,83 @@ + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml new file mode 100644 index 000000000..cebcda1b5 --- /dev/null +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml @@ -0,0 +1,83 @@ + diff --git a/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml b/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml index 4fbc1d4a6..8839e7602 100644 --- a/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml +++ b/tools/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml @@ -1,5 +1,5 @@