mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 17:00:57 -06:00
Bump github.com/gookit/config/v2 from 2.1.8 to 2.2.2
Bumps [github.com/gookit/config/v2](https://github.com/gookit/config) from 2.1.8 to 2.2.2. - [Release notes](https://github.com/gookit/config/releases) - [Commits](https://github.com/gookit/config/compare/v2.1.8...v2.2.2) --- updated-dependencies: - dependency-name: github.com/gookit/config/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
03045c5ccc
commit
5ebc596352
21
go.mod
21
go.mod
@@ -44,7 +44,7 @@ require (
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/google/go-tika v0.3.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gookit/config/v2 v2.1.8
|
||||
github.com/gookit/config/v2 v2.2.2
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.13.0
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1
|
||||
@@ -92,7 +92,7 @@ require (
|
||||
golang.org/x/image v0.6.0
|
||||
golang.org/x/net v0.10.0
|
||||
golang.org/x/oauth2 v0.8.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sync v0.2.0
|
||||
golang.org/x/term v0.8.0
|
||||
golang.org/x/text v0.9.0
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f
|
||||
@@ -108,7 +108,7 @@ require (
|
||||
require (
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
@@ -172,7 +172,7 @@ require (
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/emvi/iso-639-1 v1.0.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.5.0 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fatih/color v1.14.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gdexlab/go-render v1.0.1 // indirect
|
||||
@@ -193,10 +193,12 @@ require (
|
||||
github.com/go-resty/resty/v2 v2.7.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/go-test/deep v1.1.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.0.4 // indirect
|
||||
github.com/goccy/go-yaml v1.11.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
@@ -209,8 +211,8 @@ require (
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/gookit/goutil v0.6.0 // indirect
|
||||
github.com/gookit/color v1.5.3 // indirect
|
||||
github.com/gookit/goutil v0.6.9 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/schema v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
@@ -227,7 +229,7 @@ require (
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/iancoleman/strcase v0.2.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
@@ -242,7 +244,7 @@ require (
|
||||
github.com/longsleep/rndm v1.2.0 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
@@ -301,7 +303,7 @@ require (
|
||||
github.com/xanzy/ssh-agent v0.3.2 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/yashtewari/glob-intersection v0.1.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.7 // indirect
|
||||
@@ -320,6 +322,7 @@ require (
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
||||
73
go.sum
73
go.sum
@@ -416,8 +416,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CiscoM31/godata v1.0.7 h1:y3FHdICAU9j+IkK6E66ezCghaQSamFbYoj/YEHig0kY=
|
||||
github.com/CiscoM31/godata v1.0.7/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
|
||||
@@ -454,7 +454,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
@@ -477,9 +476,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
@@ -697,8 +693,9 @@ github.com/exoscale/egoscale v0.46.0/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
@@ -827,8 +824,11 @@ github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUri
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
@@ -841,8 +841,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
@@ -877,6 +877,8 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
|
||||
github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs=
|
||||
github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
||||
github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54=
|
||||
github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -920,7 +922,6 @@ github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3K
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v0.0.0-20170622202551-6a1fa9404c0a/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -1015,17 +1016,13 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE
|
||||
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
github.com/gookit/config/v2 v2.1.8 h1:fH8NKzOLlQ2Ud65Czy5Tq+t1I8U7M9BmIPgVFQ4T9UQ=
|
||||
github.com/gookit/config/v2 v2.1.8/go.mod h1:AP8Obh1AKx1pFkBNE2EghDb1ei2/fG33ULfkzuw4s0c=
|
||||
github.com/gookit/goutil v0.5.14/go.mod h1:ozPE16eJS9f89aVbVk05ocEJsia3KPrYUqPTs8GvUTw=
|
||||
github.com/gookit/goutil v0.5.15/go.mod h1:ozPE16eJS9f89aVbVk05ocEJsia3KPrYUqPTs8GvUTw=
|
||||
github.com/gookit/goutil v0.6.0 h1:uGne/hUNe2xiJZB77QkeIsKsdPRaPyXFv9mUdDqq/Bw=
|
||||
github.com/gookit/goutil v0.6.0/go.mod h1:DI6e4Waos7Yzjhoz75YFMpGl08m92cxNu0Tep36D/d0=
|
||||
github.com/gookit/ini/v2 v2.1.3 h1:wQPpTWbuo5GuevQnuiZMVRtALfldNuBW0XvRFgF0EEk=
|
||||
github.com/gookit/ini/v2 v2.1.3/go.mod h1:Mor4+c0wdx5UK660FBLAkmc6Yr2oBHLAUjydLQ+WgYg=
|
||||
github.com/gookit/properties v0.2.1/go.mod h1:hEmnTl5DLbGKfodoIIS698l8hqHpbhWvIznY/WAyUHc=
|
||||
github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE=
|
||||
github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE=
|
||||
github.com/gookit/config/v2 v2.2.2 h1:/iVW3H/5oPdNulrjSI370kf14Hs6D4Gc5E15u0AYxX8=
|
||||
github.com/gookit/config/v2 v2.2.2/go.mod h1:9wXrsGnOc9nLTr4mU+tuaR0ORzFyZdf3q5DuqsTyodU=
|
||||
github.com/gookit/goutil v0.6.9 h1:NrbGKt3cnWoqxjZonC5bTr0FrltTCRdzGReGQwnwhUk=
|
||||
github.com/gookit/goutil v0.6.9/go.mod h1:ZYNl/t+EIMo0rCRe1mwfC7jKyF/q1FdOEOgrXzJpr5o=
|
||||
github.com/gookit/ini/v2 v2.2.2 h1:3B8abZJrVH1vi/7TU4STuTBxdhiAq1ORSt6NJZCahaI=
|
||||
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||
github.com/gophercloud/gophercloud v0.16.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA=
|
||||
@@ -1102,7 +1099,6 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||
@@ -1126,8 +1122,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
@@ -1202,12 +1198,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
|
||||
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20230317130943-71a59c05b2c1 h1:k56sFOOJ0CYuQtGoRSeAMhP1R692+iNH+S1dC/CEz0w=
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20230317130943-71a59c05b2c1/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M=
|
||||
@@ -1257,8 +1253,9 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
@@ -1302,7 +1299,6 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
|
||||
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
|
||||
@@ -1511,7 +1507,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
|
||||
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
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=
|
||||
@@ -1556,7 +1551,6 @@ github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
@@ -1609,9 +1603,6 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/vimeo/go-util v1.4.1/go.mod h1:r+yspV//C48HeMXV8nEvtUeNiIiGfVv3bbEHzOgudwE=
|
||||
github.com/vinyldns/go-vinyldns v0.0.0-20200917153823-148a5f6b8f14/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vultr/govultr/v2 v2.0.0/go.mod h1:2PsEeg+gs3p/Fo5Pw8F9mv+DUBEOlrNZ8GmCTGmhOhs=
|
||||
github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8=
|
||||
github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk=
|
||||
@@ -1631,13 +1622,12 @@ github.com/xhit/go-simple-mail/v2 v2.13.0 h1:OANWU9jHZrVfBkNkvLf8Ww0fexwpQVF/v/5
|
||||
github.com/xhit/go-simple-mail/v2 v2.13.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yashtewari/glob-intersection v0.1.0 h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg=
|
||||
github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok=
|
||||
github.com/yosuke-furukawa/json5 v0.1.1/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -1646,9 +1636,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
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=
|
||||
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
|
||||
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
|
||||
github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go-micro.dev/v4 v4.9.0 h1:pd1CpqMT9hA47jSmX8mfdGK865PkMh95Rwj5RdfqPqE=
|
||||
go-micro.dev/v4 v4.9.0/go.mod h1:Ju8HrZ5hQSF+QguZ2QUs9Kbe42MHP1tJa/fpP5g07Cs=
|
||||
@@ -1743,9 +1730,7 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
@@ -1795,7 +1780,6 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1911,8 +1895,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -2027,7 +2012,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -2039,7 +2023,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -2152,6 +2135,7 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
@@ -2432,7 +2416,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
|
||||
4
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
4
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
@@ -91,7 +91,7 @@ const (
|
||||
// UnmarshalText method. See the Unmarshaler example for a demonstration with
|
||||
// email addresses.
|
||||
//
|
||||
// ### Key mapping
|
||||
// # Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go struct.
|
||||
// The special `toml` struct tag can be used to map TOML keys to struct fields
|
||||
@@ -248,7 +248,7 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
||||
case reflect.Bool:
|
||||
return md.unifyBool(data, rv)
|
||||
case reflect.Interface:
|
||||
if rv.NumMethod() > 0 { // Only support empty interfaces are supported.
|
||||
if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
|
||||
return md.e("unsupported type %s", rv.Type())
|
||||
}
|
||||
return md.unifyAnything(data, rv)
|
||||
|
||||
8
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
8
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
@@ -5,17 +5,25 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// TextMarshaler is an alias for encoding.TextMarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextMarshaler
|
||||
type TextMarshaler encoding.TextMarshaler
|
||||
|
||||
// TextUnmarshaler is an alias for encoding.TextUnmarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextUnmarshaler
|
||||
type TextUnmarshaler encoding.TextUnmarshaler
|
||||
|
||||
// PrimitiveDecode is an alias for MetaData.PrimitiveDecode().
|
||||
//
|
||||
// Deprecated: use MetaData.PrimitiveDecode.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]struct{})}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// DecodeReader is an alias for NewDecoder(r).Decode(v).
|
||||
//
|
||||
// Deprecated: use NewDecoder(reader).Decode(&value).
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) }
|
||||
|
||||
55
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
55
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
@@ -136,7 +136,8 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||
// document.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
rv := eindirect(reflect.ValueOf(v))
|
||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
||||
err := enc.safeEncode(Key([]string{}), rv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return enc.w.Flush()
|
||||
@@ -457,6 +458,16 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
|
||||
frv := eindirect(rv.Field(i))
|
||||
|
||||
if is32Bit {
|
||||
// Copy so it works correct on 32bit archs; not clear why this
|
||||
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||
// rare and this is a wee bit faster.
|
||||
copyStart := make([]int, len(start))
|
||||
copy(copyStart, start)
|
||||
start = copyStart
|
||||
}
|
||||
|
||||
// Treat anonymous struct fields with tag names as though they are
|
||||
// not anonymous, like encoding/json does.
|
||||
//
|
||||
@@ -471,17 +482,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
if typeIsTable(tomlTypeOfGo(frv)) {
|
||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
||||
} else {
|
||||
// Copy so it works correct on 32bit archs; not clear why this
|
||||
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||
// rare and this is a wee bit faster.
|
||||
if is32Bit {
|
||||
copyStart := make([]int, len(start))
|
||||
copy(copyStart, start)
|
||||
fieldsDirect = append(fieldsDirect, append(copyStart, f.Index...))
|
||||
} else {
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -490,24 +491,27 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
writeFields := func(fields [][]int) {
|
||||
for _, fieldIndex := range fields {
|
||||
fieldType := rt.FieldByIndex(fieldIndex)
|
||||
fieldVal := eindirect(rv.FieldByIndex(fieldIndex))
|
||||
|
||||
if isNil(fieldVal) { /// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
fieldVal := rv.FieldByIndex(fieldIndex)
|
||||
|
||||
opts := getOptions(fieldType.Tag)
|
||||
if opts.skip {
|
||||
continue
|
||||
}
|
||||
if opts.omitempty && isEmpty(fieldVal) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldVal = eindirect(fieldVal)
|
||||
|
||||
if isNil(fieldVal) { /// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
|
||||
keyName := fieldType.Name
|
||||
if opts.name != "" {
|
||||
keyName = opts.name
|
||||
}
|
||||
|
||||
if opts.omitempty && enc.isEmpty(fieldVal) {
|
||||
continue
|
||||
}
|
||||
if opts.omitzero && isZero(fieldVal) {
|
||||
continue
|
||||
}
|
||||
@@ -649,7 +653,7 @@ func isZero(rv reflect.Value) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (enc *Encoder) isEmpty(rv reflect.Value) bool {
|
||||
func isEmpty(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return rv.Len() == 0
|
||||
@@ -664,13 +668,15 @@ func (enc *Encoder) isEmpty(rv reflect.Value) bool {
|
||||
// type b struct{ s []string }
|
||||
// s := a{field: b{s: []string{"AAA"}}}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if !enc.isEmpty(rv.Field(i)) {
|
||||
if !isEmpty(rv.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
case reflect.Ptr:
|
||||
return rv.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -693,8 +699,11 @@ func (enc *Encoder) newline() {
|
||||
// v v v v vv
|
||||
// key = {k = 1, k2 = 2}
|
||||
func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) {
|
||||
/// Marshaler used on top-level document; call eElement() to just call
|
||||
/// Marshal{TOML,Text}.
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
enc.eElement(val)
|
||||
return
|
||||
}
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
|
||||
4
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
4
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
@@ -84,7 +84,7 @@ func (pe ParseError) Error() string {
|
||||
pe.Position.Line, pe.LastKey, msg)
|
||||
}
|
||||
|
||||
// ErrorWithUsage() returns the error with detailed location context.
|
||||
// ErrorWithPosition returns the error with detailed location context.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
func (pe ParseError) ErrorWithPosition() string {
|
||||
@@ -124,7 +124,7 @@ func (pe ParseError) ErrorWithPosition() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ErrorWithUsage() returns the error with detailed location context and usage
|
||||
// ErrorWithUsage returns the error with detailed location context and usage
|
||||
// guidance.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
|
||||
82
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
82
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
@@ -46,12 +46,13 @@ func (p Position) String() string {
|
||||
}
|
||||
|
||||
type lexer struct {
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
tomlNext bool
|
||||
|
||||
// Allow for backing up up to 4 runes. This is necessary because TOML
|
||||
// contains 3-rune tokens (""" and ''').
|
||||
@@ -87,13 +88,14 @@ func (lx *lexer) nextItem() item {
|
||||
}
|
||||
}
|
||||
|
||||
func lex(input string) *lexer {
|
||||
func lex(input string, tomlNext bool) *lexer {
|
||||
lx := &lexer{
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
return lx
|
||||
}
|
||||
@@ -408,7 +410,7 @@ func lexTableNameEnd(lx *lexer) stateFn {
|
||||
// Lexes only one part, e.g. only 'a' inside 'a.b'.
|
||||
func lexBareName(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isBareKeyChar(r) {
|
||||
if isBareKeyChar(r, lx.tomlNext) {
|
||||
return lexBareName
|
||||
}
|
||||
lx.backup()
|
||||
@@ -618,6 +620,9 @@ func lexInlineTableValue(lx *lexer) stateFn {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValue)
|
||||
@@ -640,6 +645,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValueEnd)
|
||||
@@ -648,6 +656,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
||||
lx.ignore()
|
||||
lx.skip(isWhitespace)
|
||||
if lx.peek() == '}' {
|
||||
if lx.tomlNext {
|
||||
return lexInlineTableValueEnd
|
||||
}
|
||||
return lx.errorf("trailing comma not allowed in inline tables")
|
||||
}
|
||||
return lexInlineTableValue
|
||||
@@ -770,8 +781,8 @@ func lexRawString(lx *lexer) stateFn {
|
||||
}
|
||||
}
|
||||
|
||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such
|
||||
// a string. It assumes that the beginning ''' has already been consumed and
|
||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such a
|
||||
// string. It assumes that the beginning triple-' has already been consumed and
|
||||
// ignored.
|
||||
func lexMultilineRawString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
@@ -828,6 +839,11 @@ func lexMultilineStringEscape(lx *lexer) stateFn {
|
||||
func lexStringEscape(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch r {
|
||||
case 'e':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
fallthrough
|
||||
case 'b':
|
||||
fallthrough
|
||||
case 't':
|
||||
@@ -846,6 +862,11 @@ func lexStringEscape(lx *lexer) stateFn {
|
||||
fallthrough
|
||||
case '\\':
|
||||
return lx.pop()
|
||||
case 'x':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
return lexHexEscape
|
||||
case 'u':
|
||||
return lexShortUnicodeEscape
|
||||
case 'U':
|
||||
@@ -854,6 +875,19 @@ func lexStringEscape(lx *lexer) stateFn {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
|
||||
func lexHexEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 2; i++ {
|
||||
r = lx.next()
|
||||
if !isHexadecimal(r) {
|
||||
return lx.errorf(
|
||||
`expected two hexadecimal digits after '\x', but got %q instead`,
|
||||
lx.current())
|
||||
}
|
||||
}
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
func lexShortUnicodeEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 4; i++ {
|
||||
@@ -1225,7 +1259,23 @@ func isOctal(r rune) bool { return r >= '0' && r <= '7' }
|
||||
func isHexadecimal(r rune) bool {
|
||||
return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F')
|
||||
}
|
||||
func isBareKeyChar(r rune) bool {
|
||||
|
||||
func isBareKeyChar(r rune, tomlNext bool) bool {
|
||||
if tomlNext {
|
||||
return (r >= 'A' && r <= 'Z') ||
|
||||
(r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
r == '_' || r == '-' ||
|
||||
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
|
||||
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
|
||||
(r >= 0x037f && r <= 0x1fff) ||
|
||||
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
|
||||
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
|
||||
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
|
||||
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
|
||||
(r >= 0x10000 && r <= 0xeffff)
|
||||
}
|
||||
|
||||
return (r >= 'A' && r <= 'Z') ||
|
||||
(r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
|
||||
2
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
2
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
@@ -106,7 +106,7 @@ func (k Key) maybeQuoted(i int) string {
|
||||
return `""`
|
||||
}
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c) {
|
||||
if !isBareKeyChar(c, false) {
|
||||
return `"` + dblQuotedReplacer.Replace(k[i]) + `"`
|
||||
}
|
||||
}
|
||||
|
||||
138
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
138
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
@@ -2,6 +2,7 @@ package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -15,6 +16,7 @@ type parser struct {
|
||||
context Key // Full key for the current hash in scope.
|
||||
currentKey string // Base key name for everything except hashes.
|
||||
pos Position // Current position in the TOML file.
|
||||
tomlNext bool
|
||||
|
||||
ordered []Key // List of keys in the order that they appear in the TOML data.
|
||||
|
||||
@@ -29,6 +31,8 @@ type keyInfo struct {
|
||||
}
|
||||
|
||||
func parse(data string) (p *parser, err error) {
|
||||
_, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if pErr, ok := r.(ParseError); ok {
|
||||
@@ -41,9 +45,12 @@ func parse(data string) (p *parser, err error) {
|
||||
}()
|
||||
|
||||
// Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString()
|
||||
// which mangles stuff.
|
||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") {
|
||||
// which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add
|
||||
// it anyway.
|
||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
|
||||
data = data[2:]
|
||||
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
|
||||
data = data[3:]
|
||||
}
|
||||
|
||||
// Examine first few bytes for NULL bytes; this probably means it's a UTF-16
|
||||
@@ -65,9 +72,10 @@ func parse(data string) (p *parser, err error) {
|
||||
p = &parser{
|
||||
keyInfo: make(map[string]keyInfo),
|
||||
mapping: make(map[string]interface{}),
|
||||
lx: lex(data),
|
||||
lx: lex(data, tomlNext),
|
||||
ordered: make([]Key, 0),
|
||||
implicits: make(map[string]struct{}),
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
for {
|
||||
item := p.next()
|
||||
@@ -194,12 +202,12 @@ func (p *parser) topLevel(item item) {
|
||||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set value.
|
||||
vItem := p.next()
|
||||
val, typ := p.value(vItem, false)
|
||||
p.set(p.currentKey, val, typ, vItem.pos)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Remove the context we added (preserving any context from [tbl] lines).
|
||||
p.context = outerContext
|
||||
@@ -236,7 +244,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) {
|
||||
case itemString:
|
||||
return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it)
|
||||
case itemMultilineString:
|
||||
return p.replaceEscapes(it, stripFirstNewline(p.stripEscapedNewlines(it.val))), p.typeOfPrimitive(it)
|
||||
return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it)
|
||||
case itemRawString:
|
||||
return it.val, p.typeOfPrimitive(it)
|
||||
case itemRawMultilineString:
|
||||
@@ -331,11 +339,17 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) {
|
||||
var dtTypes = []struct {
|
||||
fmt string
|
||||
zone *time.Location
|
||||
next bool
|
||||
}{
|
||||
{time.RFC3339Nano, time.Local},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime},
|
||||
{"2006-01-02", internal.LocalDate},
|
||||
{"15:04:05.999999999", internal.LocalTime},
|
||||
{time.RFC3339Nano, time.Local, false},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false},
|
||||
{"2006-01-02", internal.LocalDate, false},
|
||||
{"15:04:05.999999999", internal.LocalTime, false},
|
||||
|
||||
// tomlNext
|
||||
{"2006-01-02T15:04Z07:00", time.Local, true},
|
||||
{"2006-01-02T15:04", internal.LocalDatetime, true},
|
||||
{"15:04", internal.LocalTime, true},
|
||||
}
|
||||
|
||||
func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
|
||||
@@ -346,6 +360,9 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
|
||||
err error
|
||||
)
|
||||
for _, dt := range dtTypes {
|
||||
if dt.next && !p.tomlNext {
|
||||
continue
|
||||
}
|
||||
t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
|
||||
if err == nil {
|
||||
ok = true
|
||||
@@ -384,6 +401,7 @@ func (p *parser) valueArray(it item) (interface{}, tomlType) {
|
||||
//
|
||||
// Not entirely sure how to best store this; could use "key[0]",
|
||||
// "key[1]" notation, or maybe store it on the Array type?
|
||||
_ = types
|
||||
}
|
||||
return array, tomlArray
|
||||
}
|
||||
@@ -426,11 +444,11 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom
|
||||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set the value.
|
||||
val, typ := p.value(p.next(), false)
|
||||
p.set(p.currentKey, val, typ, it.pos)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
hash[p.currentKey] = val
|
||||
|
||||
/// Restore context.
|
||||
@@ -551,7 +569,6 @@ func (p *parser) addContext(key Key, array bool) {
|
||||
func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) {
|
||||
p.setValue(key, val)
|
||||
p.setType(key, typ, pos)
|
||||
|
||||
}
|
||||
|
||||
// setValue sets the given key to the given value in the current context.
|
||||
@@ -632,14 +649,11 @@ func (p *parser) setType(key string, typ tomlType, pos Position) {
|
||||
|
||||
// Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
|
||||
// "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
|
||||
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
|
||||
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
|
||||
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
|
||||
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
|
||||
func (p *parser) addImplicitContext(key Key) {
|
||||
p.addImplicit(key)
|
||||
p.addContext(key, false)
|
||||
}
|
||||
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
|
||||
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
|
||||
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
|
||||
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
|
||||
func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) }
|
||||
|
||||
// current returns the full key name of the current context.
|
||||
func (p *parser) current() string {
|
||||
@@ -662,49 +676,54 @@ func stripFirstNewline(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// Remove newlines inside triple-quoted strings if a line ends with "\".
|
||||
// stripEscapedNewlines removes whitespace after line-ending backslashes in
|
||||
// multiline strings.
|
||||
//
|
||||
// A line-ending backslash is an unescaped \ followed only by whitespace until
|
||||
// the next newline. After a line-ending backslash, all whitespace is removed
|
||||
// until the next non-whitespace character.
|
||||
func (p *parser) stripEscapedNewlines(s string) string {
|
||||
split := strings.Split(s, "\n")
|
||||
if len(split) < 1 {
|
||||
return s
|
||||
}
|
||||
var b strings.Builder
|
||||
var i int
|
||||
for {
|
||||
ix := strings.Index(s[i:], `\`)
|
||||
if ix < 0 {
|
||||
b.WriteString(s)
|
||||
return b.String()
|
||||
}
|
||||
i += ix
|
||||
|
||||
escNL := false // Keep track of the last non-blank line was escaped.
|
||||
for i, line := range split {
|
||||
line = strings.TrimRight(line, " \t\r")
|
||||
|
||||
if len(line) == 0 || line[len(line)-1] != '\\' {
|
||||
split[i] = strings.TrimRight(split[i], "\r")
|
||||
if !escNL && i != len(split)-1 {
|
||||
split[i] += "\n"
|
||||
if len(s) > i+1 && s[i+1] == '\\' {
|
||||
// Escaped backslash.
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
// Scan until the next non-whitespace.
|
||||
j := i + 1
|
||||
whitespaceLoop:
|
||||
for ; j < len(s); j++ {
|
||||
switch s[j] {
|
||||
case ' ', '\t', '\r', '\n':
|
||||
default:
|
||||
break whitespaceLoop
|
||||
}
|
||||
}
|
||||
if j == i+1 {
|
||||
// Not a whitespace escape.
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
escBS := true
|
||||
for j := len(line) - 1; j >= 0 && line[j] == '\\'; j-- {
|
||||
escBS = !escBS
|
||||
}
|
||||
if escNL {
|
||||
line = strings.TrimLeft(line, " \t\r")
|
||||
}
|
||||
escNL = !escBS
|
||||
|
||||
if escBS {
|
||||
split[i] += "\n"
|
||||
if !strings.Contains(s[i:j], "\n") {
|
||||
// This is not a line-ending backslash.
|
||||
// (It's a bad escape sequence, but we can let
|
||||
// replaceEscapes catch it.)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if i == len(split)-1 {
|
||||
p.panicf("invalid escape: '\\ '")
|
||||
}
|
||||
|
||||
split[i] = line[:len(line)-1] // Remove \
|
||||
if len(split)-1 > i {
|
||||
split[i+1] = strings.TrimLeft(split[i+1], " \t\r")
|
||||
}
|
||||
b.WriteString(s[:i])
|
||||
s = s[j:]
|
||||
i = 0
|
||||
}
|
||||
return strings.Join(split, "")
|
||||
}
|
||||
|
||||
func (p *parser) replaceEscapes(it item, str string) string {
|
||||
@@ -743,12 +762,23 @@ func (p *parser) replaceEscapes(it item, str string) string {
|
||||
case 'r':
|
||||
replaced = append(replaced, rune(0x000D))
|
||||
r += 1
|
||||
case 'e':
|
||||
if p.tomlNext {
|
||||
replaced = append(replaced, rune(0x001B))
|
||||
r += 1
|
||||
}
|
||||
case '"':
|
||||
replaced = append(replaced, rune(0x0022))
|
||||
r += 1
|
||||
case '\\':
|
||||
replaced = append(replaced, rune(0x005C))
|
||||
r += 1
|
||||
case 'x':
|
||||
if p.tomlNext {
|
||||
escaped := p.asciiEscapeToUnicode(it, s[r+1:r+3])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 3
|
||||
}
|
||||
case 'u':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
|
||||
|
||||
14
vendor/github.com/fatih/color/README.md
generated
vendored
14
vendor/github.com/fatih/color/README.md
generated
vendored
@@ -7,7 +7,6 @@ suits you.
|
||||
|
||||

|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
@@ -124,17 +123,17 @@ fmt.Println("All text will now be bold magenta.")
|
||||
```
|
||||
|
||||
### Disable/Enable color
|
||||
|
||||
|
||||
There might be a case where you want to explicitly disable/enable color output. the
|
||||
`go-isatty` package will automatically disable color output for non-tty output streams
|
||||
(for example if the output were piped directly to `less`).
|
||||
|
||||
The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
|
||||
variable is set (regardless of its value).
|
||||
variable is set to a non-empty string.
|
||||
|
||||
`Color` has support to disable/enable colors programatically both globally and
|
||||
`Color` has support to disable/enable colors programmatically both globally and
|
||||
for single color definitions. For example suppose you have a CLI app and a
|
||||
`--no-color` bool flag. You can easily disable the color output with:
|
||||
`-no-color` bool flag. You can easily disable the color output with:
|
||||
|
||||
```go
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
@@ -167,11 +166,10 @@ To output color in GitHub Actions (or other CI systems that support ANSI colors)
|
||||
* Save/Return previous values
|
||||
* Evaluate fmt.Formatter interface
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
* [Fatih Arslan](https://github.com/fatih)
|
||||
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)
|
||||
* [Fatih Arslan](https://github.com/fatih)
|
||||
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
46
vendor/github.com/fatih/color/color.go
generated
vendored
46
vendor/github.com/fatih/color/color.go
generated
vendored
@@ -19,10 +19,10 @@ var (
|
||||
// set (regardless of its value). This is a global option and affects all
|
||||
// colors. For more control over each color block use the methods
|
||||
// DisableColor() individually.
|
||||
NoColor = noColorExists() || os.Getenv("TERM") == "dumb" ||
|
||||
NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" ||
|
||||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
|
||||
|
||||
// Output defines the standard output of the print functions. By default
|
||||
// Output defines the standard output of the print functions. By default,
|
||||
// os.Stdout is used.
|
||||
Output = colorable.NewColorableStdout()
|
||||
|
||||
@@ -35,10 +35,9 @@ var (
|
||||
colorsCacheMu sync.Mutex // protects colorsCache
|
||||
)
|
||||
|
||||
// noColorExists returns true if the environment variable NO_COLOR exists.
|
||||
func noColorExists() bool {
|
||||
_, exists := os.LookupEnv("NO_COLOR")
|
||||
return exists
|
||||
// noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string.
|
||||
func noColorIsSet() bool {
|
||||
return os.Getenv("NO_COLOR") != ""
|
||||
}
|
||||
|
||||
// Color defines a custom color object which is defined by SGR parameters.
|
||||
@@ -120,7 +119,7 @@ func New(value ...Attribute) *Color {
|
||||
params: make([]Attribute, 0),
|
||||
}
|
||||
|
||||
if noColorExists() {
|
||||
if noColorIsSet() {
|
||||
c.noColor = boolPtr(true)
|
||||
}
|
||||
|
||||
@@ -152,7 +151,7 @@ func (c *Color) Set() *Color {
|
||||
return c
|
||||
}
|
||||
|
||||
fmt.Fprintf(Output, c.format())
|
||||
fmt.Fprint(Output, c.format())
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -164,16 +163,21 @@ func (c *Color) unset() {
|
||||
Unset()
|
||||
}
|
||||
|
||||
func (c *Color) setWriter(w io.Writer) *Color {
|
||||
// SetWriter is used to set the SGR sequence with the given io.Writer. This is
|
||||
// a low-level function, and users should use the higher-level functions, such
|
||||
// as color.Fprint, color.Print, etc.
|
||||
func (c *Color) SetWriter(w io.Writer) *Color {
|
||||
if c.isNoColorSet() {
|
||||
return c
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, c.format())
|
||||
fmt.Fprint(w, c.format())
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Color) unsetWriter(w io.Writer) {
|
||||
// UnsetWriter resets all escape attributes and clears the output with the give
|
||||
// io.Writer. Usually should be called after SetWriter().
|
||||
func (c *Color) UnsetWriter(w io.Writer) {
|
||||
if c.isNoColorSet() {
|
||||
return
|
||||
}
|
||||
@@ -192,20 +196,14 @@ func (c *Color) Add(value ...Attribute) *Color {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Color) prepend(value Attribute) {
|
||||
c.params = append(c.params, 0)
|
||||
copy(c.params[1:], c.params[0:])
|
||||
c.params[0] = value
|
||||
}
|
||||
|
||||
// Fprint formats using the default formats for its operands and writes to w.
|
||||
// Spaces are added between operands when neither is a string.
|
||||
// It returns the number of bytes written and any write error encountered.
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
c.SetWriter(w)
|
||||
defer c.UnsetWriter(w)
|
||||
|
||||
return fmt.Fprint(w, a...)
|
||||
}
|
||||
@@ -227,8 +225,8 @@ func (c *Color) Print(a ...interface{}) (n int, err error) {
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
c.SetWriter(w)
|
||||
defer c.UnsetWriter(w)
|
||||
|
||||
return fmt.Fprintf(w, format, a...)
|
||||
}
|
||||
@@ -248,8 +246,8 @@ func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
c.SetWriter(w)
|
||||
defer c.UnsetWriter(w)
|
||||
|
||||
return fmt.Fprintln(w, a...)
|
||||
}
|
||||
@@ -396,7 +394,7 @@ func (c *Color) DisableColor() {
|
||||
}
|
||||
|
||||
// EnableColor enables the color output. Use it in conjunction with
|
||||
// DisableColor(). Otherwise this method has no side effects.
|
||||
// DisableColor(). Otherwise, this method has no side effects.
|
||||
func (c *Color) EnableColor() {
|
||||
c.noColor = boolPtr(false)
|
||||
}
|
||||
|
||||
137
vendor/github.com/fatih/color/doc.go
generated
vendored
137
vendor/github.com/fatih/color/doc.go
generated
vendored
@@ -5,106 +5,105 @@ that suits you.
|
||||
|
||||
Use simple and default helper functions with predefined foreground colors:
|
||||
|
||||
color.Cyan("Prints text in cyan.")
|
||||
color.Cyan("Prints text in cyan.")
|
||||
|
||||
// a newline will be appended automatically
|
||||
color.Blue("Prints %s in blue.", "text")
|
||||
// a newline will be appended automatically
|
||||
color.Blue("Prints %s in blue.", "text")
|
||||
|
||||
// More default foreground colors..
|
||||
color.Red("We have red")
|
||||
color.Yellow("Yellow color too!")
|
||||
color.Magenta("And many others ..")
|
||||
// More default foreground colors..
|
||||
color.Red("We have red")
|
||||
color.Yellow("Yellow color too!")
|
||||
color.Magenta("And many others ..")
|
||||
|
||||
// Hi-intensity colors
|
||||
color.HiGreen("Bright green color.")
|
||||
color.HiBlack("Bright black means gray..")
|
||||
color.HiWhite("Shiny white color!")
|
||||
// Hi-intensity colors
|
||||
color.HiGreen("Bright green color.")
|
||||
color.HiBlack("Bright black means gray..")
|
||||
color.HiWhite("Shiny white color!")
|
||||
|
||||
However there are times where custom color mixes are required. Below are some
|
||||
However, there are times when custom color mixes are required. Below are some
|
||||
examples to create custom color objects and use the print functions of each
|
||||
separate color object.
|
||||
|
||||
// Create a new color object
|
||||
c := color.New(color.FgCyan).Add(color.Underline)
|
||||
c.Println("Prints cyan text with an underline.")
|
||||
// Create a new color object
|
||||
c := color.New(color.FgCyan).Add(color.Underline)
|
||||
c.Println("Prints cyan text with an underline.")
|
||||
|
||||
// Or just add them to New()
|
||||
d := color.New(color.FgCyan, color.Bold)
|
||||
d.Printf("This prints bold cyan %s\n", "too!.")
|
||||
// Or just add them to New()
|
||||
d := color.New(color.FgCyan, color.Bold)
|
||||
d.Printf("This prints bold cyan %s\n", "too!.")
|
||||
|
||||
|
||||
// Mix up foreground and background colors, create new mixes!
|
||||
red := color.New(color.FgRed)
|
||||
// Mix up foreground and background colors, create new mixes!
|
||||
red := color.New(color.FgRed)
|
||||
|
||||
boldRed := red.Add(color.Bold)
|
||||
boldRed.Println("This will print text in bold red.")
|
||||
boldRed := red.Add(color.Bold)
|
||||
boldRed.Println("This will print text in bold red.")
|
||||
|
||||
whiteBackground := red.Add(color.BgWhite)
|
||||
whiteBackground.Println("Red text with White background.")
|
||||
whiteBackground := red.Add(color.BgWhite)
|
||||
whiteBackground.Println("Red text with White background.")
|
||||
|
||||
// Use your own io.Writer output
|
||||
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
|
||||
// Use your own io.Writer output
|
||||
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
|
||||
|
||||
blue := color.New(color.FgBlue)
|
||||
blue.Fprint(myWriter, "This will print text in blue.")
|
||||
blue := color.New(color.FgBlue)
|
||||
blue.Fprint(myWriter, "This will print text in blue.")
|
||||
|
||||
You can create PrintXxx functions to simplify even more:
|
||||
|
||||
// Create a custom print function for convenient
|
||||
red := color.New(color.FgRed).PrintfFunc()
|
||||
red("warning")
|
||||
red("error: %s", err)
|
||||
// Create a custom print function for convenient
|
||||
red := color.New(color.FgRed).PrintfFunc()
|
||||
red("warning")
|
||||
red("error: %s", err)
|
||||
|
||||
// Mix up multiple attributes
|
||||
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
|
||||
notice("don't forget this...")
|
||||
// Mix up multiple attributes
|
||||
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
|
||||
notice("don't forget this...")
|
||||
|
||||
You can also FprintXxx functions to pass your own io.Writer:
|
||||
|
||||
blue := color.New(FgBlue).FprintfFunc()
|
||||
blue(myWriter, "important notice: %s", stars)
|
||||
|
||||
// Mix up with multiple attributes
|
||||
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
|
||||
success(myWriter, don't forget this...")
|
||||
blue := color.New(FgBlue).FprintfFunc()
|
||||
blue(myWriter, "important notice: %s", stars)
|
||||
|
||||
// Mix up with multiple attributes
|
||||
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
|
||||
success(myWriter, don't forget this...")
|
||||
|
||||
Or create SprintXxx functions to mix strings with other non-colorized strings:
|
||||
|
||||
yellow := New(FgYellow).SprintFunc()
|
||||
red := New(FgRed).SprintFunc()
|
||||
yellow := New(FgYellow).SprintFunc()
|
||||
red := New(FgRed).SprintFunc()
|
||||
|
||||
fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
|
||||
fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
|
||||
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Printf("this %s rocks!\n", info("package"))
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Printf("this %s rocks!\n", info("package"))
|
||||
|
||||
Windows support is enabled by default. All Print functions work as intended.
|
||||
However only for color.SprintXXX functions, user should use fmt.FprintXXX and
|
||||
However, only for color.SprintXXX functions, user should use fmt.FprintXXX and
|
||||
set the output to color.Output:
|
||||
|
||||
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
|
||||
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
|
||||
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
|
||||
|
||||
Using with existing code is possible. Just use the Set() method to set the
|
||||
standard output to the given parameters. That way a rewrite of an existing
|
||||
code is not required.
|
||||
|
||||
// Use handy standard colors.
|
||||
color.Set(color.FgYellow)
|
||||
// Use handy standard colors.
|
||||
color.Set(color.FgYellow)
|
||||
|
||||
fmt.Println("Existing text will be now in Yellow")
|
||||
fmt.Printf("This one %s\n", "too")
|
||||
fmt.Println("Existing text will be now in Yellow")
|
||||
fmt.Printf("This one %s\n", "too")
|
||||
|
||||
color.Unset() // don't forget to unset
|
||||
color.Unset() // don't forget to unset
|
||||
|
||||
// You can mix up parameters
|
||||
color.Set(color.FgMagenta, color.Bold)
|
||||
defer color.Unset() // use it in your function
|
||||
// You can mix up parameters
|
||||
color.Set(color.FgMagenta, color.Bold)
|
||||
defer color.Unset() // use it in your function
|
||||
|
||||
fmt.Println("All text will be now bold magenta.")
|
||||
fmt.Println("All text will be now bold magenta.")
|
||||
|
||||
There might be a case where you want to disable color output (for example to
|
||||
pipe the standard output of your app to somewhere else). `Color` has support to
|
||||
@@ -112,24 +111,24 @@ disable colors both globally and for single color definition. For example
|
||||
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
|
||||
the color output with:
|
||||
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
|
||||
if *flagNoColor {
|
||||
color.NoColor = true // disables colorized output
|
||||
}
|
||||
if *flagNoColor {
|
||||
color.NoColor = true // disables colorized output
|
||||
}
|
||||
|
||||
You can also disable the color by setting the NO_COLOR environment variable to any value.
|
||||
|
||||
It also has support for single color definitions (local). You can
|
||||
disable/enable color output on the fly:
|
||||
|
||||
c := color.New(color.FgCyan)
|
||||
c.Println("Prints cyan text")
|
||||
c := color.New(color.FgCyan)
|
||||
c.Println("Prints cyan text")
|
||||
|
||||
c.DisableColor()
|
||||
c.Println("This is printed without any color")
|
||||
c.DisableColor()
|
||||
c.Println("This is printed without any color")
|
||||
|
||||
c.EnableColor()
|
||||
c.Println("This prints again cyan...")
|
||||
c.EnableColor()
|
||||
c.Println("This prints again cyan...")
|
||||
*/
|
||||
package color
|
||||
|
||||
31
vendor/github.com/goccy/go-yaml/.codecov.yml
generated
vendored
Normal file
31
vendor/github.com/goccy/go-yaml/.codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
codecov:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 75%
|
||||
threshold: 2%
|
||||
patch: off
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "header,diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
|
||||
ignore:
|
||||
- ast
|
||||
163
vendor/github.com/goccy/go-yaml/CHANGELOG.md
generated
vendored
Normal file
163
vendor/github.com/goccy/go-yaml/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
# 1.10.1 - 2023-03-28
|
||||
|
||||
### Features
|
||||
|
||||
- Quote YAML 1.1 bools at encoding time for compatibility with other legacy parsers
|
||||
- Add support of 32-bit architecture
|
||||
|
||||
### Fix bugs
|
||||
|
||||
- Don't trim all space characters in block style sequence
|
||||
- Support strings starting with `@`
|
||||
|
||||
# 1.10.0 - 2023-03-01
|
||||
|
||||
### Fix bugs
|
||||
|
||||
Reversible conversion of comments was not working in various cases, which has been corrected.
|
||||
**Breaking Change** exists in the comment map interface. However, if you are dealing with CommentMap directly, there is no problem.
|
||||
|
||||
|
||||
# 1.9.8 - 2022-12-19
|
||||
|
||||
### Fix feature
|
||||
|
||||
- Append new line at the end of file ( #329 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
- Fix custom marshaler ( #333, #334 )
|
||||
- Fix behavior when struct fields conflicted( #335 )
|
||||
- Fix position calculation for literal, folded and raw folded strings ( #330 )
|
||||
|
||||
# 1.9.7 - 2022-12-03
|
||||
|
||||
### Fix bugs
|
||||
|
||||
- Fix handling of quoted map key ( #328 )
|
||||
- Fix resusing process of scanning context ( #322 )
|
||||
|
||||
## v1.9.6 - 2022-10-26
|
||||
|
||||
### New Features
|
||||
|
||||
- Introduce MapKeyNode interface to limit node types for map key ( #312 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
- Quote strings with special characters in flow mode ( #270 )
|
||||
- typeError implements PrettyPrinter interface ( #280 )
|
||||
- Fix incorrect const type ( #284 )
|
||||
- Fix large literals type inference on 32 bits ( #293 )
|
||||
- Fix UTF-8 characters ( #294 )
|
||||
- Fix decoding of unknown aliases ( #317 )
|
||||
- Fix stream encoder for insert a separator between each encoded document ( #318 )
|
||||
|
||||
### Update
|
||||
|
||||
- Update golang.org/x/sys ( #289 )
|
||||
- Update Go version in CI ( #295 )
|
||||
- Add test cases for missing keys to struct literals ( #300 )
|
||||
|
||||
## v1.9.5 - 2022-01-12
|
||||
|
||||
### New Features
|
||||
|
||||
* Add UseSingleQuote option ( #265 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Preserve defaults while decoding nested structs ( #260 )
|
||||
* Fix minor typo in decodeInit error ( #264 )
|
||||
* Handle empty sequence entries ( #275 )
|
||||
* Fix encoding of sequence with multiline string ( #276 )
|
||||
* Fix encoding of BytesMarshaler type ( #277 )
|
||||
* Fix indentState logic for multi-line value ( #278 )
|
||||
|
||||
## v1.9.4 - 2021-10-12
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Keep prev/next reference between tokens containing comments when filtering comment tokens ( #257 )
|
||||
* Supports escaping reserved keywords in PathBuilder ( #258 )
|
||||
|
||||
## v1.9.3 - 2021-09-07
|
||||
|
||||
### New Features
|
||||
|
||||
* Support encoding and decoding `time.Duration` fields ( #246 )
|
||||
* Allow reserved characters for key name in YAMLPath ( #251 )
|
||||
* Support getting YAMLPath from ast.Node ( #252 )
|
||||
* Support CommentToMap option ( #253 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix encoding nested sequences with `yaml.IndentSequence` ( #241 )
|
||||
* Fix error reporting on inline structs in strict mode ( #244, #245 )
|
||||
* Fix encoding of large floats ( #247 )
|
||||
|
||||
### Improve workflow
|
||||
|
||||
* Migrate CI from CircleCI to GitHub Action ( #249 )
|
||||
* Add workflow for ycat ( #250 )
|
||||
|
||||
## v1.9.2 - 2021-07-26
|
||||
|
||||
### Support WithComment option ( #238 )
|
||||
|
||||
`yaml.WithComment` is a option for encoding with comment.
|
||||
The position where you want to add a comment is represented by YAMLPath, and it is the key of `yaml.CommentMap`.
|
||||
Also, you can select `Head` comment or `Line` comment as the comment type.
|
||||
|
||||
## v1.9.1 - 2021-07-20
|
||||
|
||||
### Fix DecodeFromNode ( #237 )
|
||||
|
||||
- Fix YAML handling where anchor exists
|
||||
|
||||
## v1.9.0 - 2021-07-19
|
||||
|
||||
### New features
|
||||
|
||||
- Support encoding of comment node ( #233 )
|
||||
- Support `yaml.NodeToValue(ast.Node, interface{}, ...DecodeOption) error` ( #236 )
|
||||
- Can convert a AST node to a value directly
|
||||
|
||||
### Fix decoder for comment
|
||||
|
||||
- Fix parsing of literal with comment ( #234 )
|
||||
|
||||
### Rename API ( #235 )
|
||||
|
||||
- Rename `MarshalWithContext` to `MarshalContext`
|
||||
- Rename `UnmarshalWithContext` to `UnmarshalContext`
|
||||
|
||||
## v1.8.10 - 2021-07-02
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
- Fix searching anchor by alias name ( #212 )
|
||||
- Fixing Issue 186, scanner should account for newline characters when processing multi-line text. Without this source annotations line/column number (for this and all subsequent tokens) is inconsistent with plain text editors. e.g. https://github.com/goccy/go-yaml/issues/186. This addresses the issue specifically for single and double quote text only. ( #210 )
|
||||
- Add error for unterminated flow mapping node ( #213 )
|
||||
- Handle missing required field validation ( #221 )
|
||||
- Nicely format unexpected node type errors ( #229 )
|
||||
- Support to encode map which has defined type key ( #231 )
|
||||
|
||||
### New features
|
||||
|
||||
- Support sequence indentation by EncodeOption ( #232 )
|
||||
|
||||
## v1.8.9 - 2021-03-01
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
- Fix origin buffer for DocumentHeader and DocumentEnd and Directive
|
||||
- Fix origin buffer for anchor value
|
||||
- Fix syntax error about map value
|
||||
- Fix parsing MergeKey ('<<') characters
|
||||
- Fix encoding of float value
|
||||
- Fix incorrect column annotation when single or double quotes are used
|
||||
|
||||
### New features
|
||||
|
||||
- Support to encode/decode of ast.Node directly
|
||||
21
vendor/github.com/goccy/go-yaml/LICENSE
generated
vendored
Normal file
21
vendor/github.com/goccy/go-yaml/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Masaaki Goshima
|
||||
|
||||
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.
|
||||
19
vendor/github.com/goccy/go-yaml/Makefile
generated
vendored
Normal file
19
vendor/github.com/goccy/go-yaml/Makefile
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race ./...
|
||||
|
||||
.PHONY: simple-test
|
||||
simple-test:
|
||||
go test -v ./...
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -coverprofile=cover.out ./...
|
||||
|
||||
.PHONY: cover-html
|
||||
cover-html: cover
|
||||
go tool cover -html=cover.out
|
||||
|
||||
.PHONY: ycat/build
|
||||
ycat/build:
|
||||
go build -o ycat ./cmd/ycat
|
||||
370
vendor/github.com/goccy/go-yaml/README.md
generated
vendored
Normal file
370
vendor/github.com/goccy/go-yaml/README.md
generated
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
# YAML support for the Go language
|
||||
|
||||
[](https://pkg.go.dev/github.com/goccy/go-yaml)
|
||||

|
||||
[](https://codecov.io/gh/goccy/go-yaml)
|
||||
[](https://goreportcard.com/report/github.com/goccy/go-yaml)
|
||||
|
||||
<img width="300px" src="https://user-images.githubusercontent.com/209884/67159116-64d94b80-f37b-11e9-9b28-f8379636a43c.png"></img>
|
||||
|
||||
# Why a new library?
|
||||
|
||||
As of this writing, there already exists a de facto standard library for YAML processing for Go: [https://github.com/go-yaml/yaml](https://github.com/go-yaml/yaml). However we feel that some features are lacking, namely:
|
||||
|
||||
- Pretty format for error notifications
|
||||
- Direct manipulation of YAML abstract syntax tree
|
||||
- Support for `Anchor` and `Alias` when marshaling
|
||||
- Allow referencing elements declared in another file via anchors
|
||||
|
||||
# Features
|
||||
|
||||
- Pretty format for error notifications
|
||||
- Supports `Scanner` or `Lexer` or `Parser` as public API
|
||||
- Supports `Anchor` and `Alias` to Marshaler
|
||||
- Allow referencing elements declared in another file via anchors
|
||||
- Extract value or AST by YAMLPath ( YAMLPath is like a JSONPath )
|
||||
|
||||
# Installation
|
||||
|
||||
```sh
|
||||
go get -u github.com/goccy/go-yaml
|
||||
```
|
||||
|
||||
# Synopsis
|
||||
|
||||
## 1. Simple Encode/Decode
|
||||
|
||||
Has an interface like `go-yaml/yaml` using `reflect`
|
||||
|
||||
```go
|
||||
var v struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
v.A = 1
|
||||
v.B = "hello"
|
||||
bytes, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
//...
|
||||
}
|
||||
fmt.Println(string(bytes)) // "a: 1\nb: hello\n"
|
||||
```
|
||||
|
||||
```go
|
||||
yml := `
|
||||
%YAML 1.2
|
||||
---
|
||||
a: 1
|
||||
b: c
|
||||
`
|
||||
var v struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
To control marshal/unmarshal behavior, you can use the `yaml` tag.
|
||||
|
||||
```go
|
||||
yml := `---
|
||||
foo: 1
|
||||
bar: c
|
||||
`
|
||||
var v struct {
|
||||
A int `yaml:"foo"`
|
||||
B string `yaml:"bar"`
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
For convenience, we also accept the `json` tag. Note that not all options from
|
||||
the `json` tag will have significance when parsing YAML documents. If both
|
||||
tags exist, `yaml` tag will take precedence.
|
||||
|
||||
```go
|
||||
yml := `---
|
||||
foo: 1
|
||||
bar: c
|
||||
`
|
||||
var v struct {
|
||||
A int `json:"foo"`
|
||||
B string `json:"bar"`
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
For custom marshal/unmarshaling, implement either `Bytes` or `Interface` variant of marshaler/unmarshaler. The difference is that while `BytesMarshaler`/`BytesUnmarshaler` behaves like [`encoding/json`](https://pkg.go.dev/encoding/json) and `InterfaceMarshaler`/`InterfaceUnmarshaler` behaves like [`gopkg.in/yaml.v2`](https://pkg.go.dev/gopkg.in/yaml.v2).
|
||||
|
||||
Semantically both are the same, but they differ in performance. Because indentation matters in YAML, you cannot simply accept a valid YAML fragment from a Marshaler, and expect it to work when it is attached to the parent container's serialized form. Therefore when we receive use the `BytesMarshaler`, which returns `[]byte`, we must decode it once to figure out how to make it work in the given context. If you use the `InterfaceMarshaler`, we can skip the decoding.
|
||||
|
||||
If you are repeatedly marshaling complex objects, the latter is always better
|
||||
performance wise. But if you are, for example, just providing a choice between
|
||||
a config file format that is read only once, the former is probably easier to
|
||||
code.
|
||||
|
||||
## 2. Reference elements declared in another file
|
||||
|
||||
`testdata` directory contains `anchor.yml` file:
|
||||
|
||||
```shell
|
||||
├── testdata
|
||||
└── anchor.yml
|
||||
```
|
||||
|
||||
And `anchor.yml` is defined as follows:
|
||||
|
||||
```yaml
|
||||
a: &a
|
||||
b: 1
|
||||
c: hello
|
||||
```
|
||||
|
||||
Then, if `yaml.ReferenceDirs("testdata")` option is passed to `yaml.Decoder`,
|
||||
`Decoder` tries to find the anchor definition from YAML files the under `testdata` directory.
|
||||
|
||||
```go
|
||||
buf := bytes.NewBufferString("a: *a\n")
|
||||
dec := yaml.NewDecoder(buf, yaml.ReferenceDirs("testdata"))
|
||||
var v struct {
|
||||
A struct {
|
||||
B int
|
||||
C string
|
||||
}
|
||||
}
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
//...
|
||||
}
|
||||
fmt.Printf("%+v\n", v) // {A:{B:1 C:hello}}
|
||||
```
|
||||
|
||||
## 3. Encode with `Anchor` and `Alias`
|
||||
|
||||
### 3.1. Explicitly declared `Anchor` name and `Alias` name
|
||||
|
||||
If you want to use `anchor` or `alias`, you can define it as a struct tag.
|
||||
|
||||
```go
|
||||
type T struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
var v struct {
|
||||
C *T `yaml:"c,anchor=x"`
|
||||
D *T `yaml:"d,alias=x"`
|
||||
}
|
||||
v.C = &T{A: 1, B: "hello"}
|
||||
v.D = v.C
|
||||
bytes, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(bytes))
|
||||
/*
|
||||
c: &x
|
||||
a: 1
|
||||
b: hello
|
||||
d: *x
|
||||
*/
|
||||
```
|
||||
|
||||
### 3.2. Implicitly declared `Anchor` and `Alias` names
|
||||
|
||||
If you do not explicitly declare the anchor name, the default behavior is to
|
||||
use the equivalent of `strings.ToLower($FieldName)` as the name of the anchor.
|
||||
|
||||
If you do not explicitly declare the alias name AND the value is a pointer
|
||||
to another element, we look up the anchor name by finding out which anchor
|
||||
field the value is assigned to by looking up its pointer address.
|
||||
|
||||
```go
|
||||
type T struct {
|
||||
I int
|
||||
S string
|
||||
}
|
||||
var v struct {
|
||||
A *T `yaml:"a,anchor"`
|
||||
B *T `yaml:"b,anchor"`
|
||||
C *T `yaml:"c,alias"`
|
||||
D *T `yaml:"d,alias"`
|
||||
}
|
||||
v.A = &T{I: 1, S: "hello"}
|
||||
v.B = &T{I: 2, S: "world"}
|
||||
v.C = v.A // C has same pointer address to A
|
||||
v.D = v.B // D has same pointer address to B
|
||||
bytes, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
//...
|
||||
}
|
||||
fmt.Println(string(bytes))
|
||||
/*
|
||||
a: &a
|
||||
i: 1
|
||||
s: hello
|
||||
b: &b
|
||||
i: 2
|
||||
s: world
|
||||
c: *a
|
||||
d: *b
|
||||
*/
|
||||
```
|
||||
|
||||
### 3.3 MergeKey and Alias
|
||||
|
||||
Merge key and alias ( `<<: *alias` ) can be used by embedding a structure with the `inline,alias` tag.
|
||||
|
||||
```go
|
||||
type Person struct {
|
||||
*Person `yaml:",omitempty,inline,alias"` // embed Person type for default value
|
||||
Name string `yaml:",omitempty"`
|
||||
Age int `yaml:",omitempty"`
|
||||
}
|
||||
defaultPerson := &Person{
|
||||
Name: "John Smith",
|
||||
Age: 20,
|
||||
}
|
||||
people := []*Person{
|
||||
{
|
||||
Person: defaultPerson, // assign default value
|
||||
Name: "Ken", // override Name property
|
||||
Age: 10, // override Age property
|
||||
},
|
||||
{
|
||||
Person: defaultPerson, // assign default value only
|
||||
},
|
||||
}
|
||||
var doc struct {
|
||||
Default *Person `yaml:"default,anchor"`
|
||||
People []*Person `yaml:"people"`
|
||||
}
|
||||
doc.Default = defaultPerson
|
||||
doc.People = people
|
||||
bytes, err := yaml.Marshal(doc)
|
||||
if err != nil {
|
||||
//...
|
||||
}
|
||||
fmt.Println(string(bytes))
|
||||
/*
|
||||
default: &default
|
||||
name: John Smith
|
||||
age: 20
|
||||
people:
|
||||
- <<: *default
|
||||
name: Ken
|
||||
age: 10
|
||||
- <<: *default
|
||||
*/
|
||||
```
|
||||
|
||||
## 4. Pretty Formatted Errors
|
||||
|
||||
Error values produced during parsing have two extra features over regular
|
||||
error values.
|
||||
|
||||
First, by default, they contain extra information on the location of the error
|
||||
from the source YAML document, to make it easier to find the error location.
|
||||
|
||||
Second, the error messages can optionally be colorized.
|
||||
|
||||
If you would like to control exactly how the output looks like, consider
|
||||
using `yaml.FormatError`, which accepts two boolean values to
|
||||
control turning these features on or off.
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/209884/67358124-587f0980-f59a-11e9-96fc-7205aab77695.png"></img>
|
||||
|
||||
## 5. Use YAMLPath
|
||||
|
||||
```go
|
||||
yml := `
|
||||
store:
|
||||
book:
|
||||
- author: john
|
||||
price: 10
|
||||
- author: ken
|
||||
price: 12
|
||||
bicycle:
|
||||
color: red
|
||||
price: 19.95
|
||||
`
|
||||
path, err := yaml.PathString("$.store.book[*].author")
|
||||
if err != nil {
|
||||
//...
|
||||
}
|
||||
var authors []string
|
||||
if err := path.Read(strings.NewReader(yml), &authors); err != nil {
|
||||
//...
|
||||
}
|
||||
fmt.Println(authors)
|
||||
// [john ken]
|
||||
```
|
||||
|
||||
### 5.1 Print customized error with YAML source code
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
yml := `
|
||||
a: 1
|
||||
b: "hello"
|
||||
`
|
||||
var v struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if v.A != 2 {
|
||||
// output error with YAML source
|
||||
path, err := yaml.PathString("$.a")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
source, err := path.AnnotateSource([]byte(yml), true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("a value expected 2 but actual %d:\n%s\n", v.A, string(source))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
output result is the following:
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/209884/84148813-7aca8680-aa9a-11ea-8fc9-37dece2ebdac.png"></img>
|
||||
|
||||
|
||||
# Tools
|
||||
|
||||
## ycat
|
||||
|
||||
print yaml file with color
|
||||
|
||||
<img width="713" alt="ycat" src="https://user-images.githubusercontent.com/209884/66986084-19b00600-f0f9-11e9-9f0e-1f91eb072fe0.png">
|
||||
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
go install github.com/goccy/go-yaml/cmd/ycat@latest
|
||||
```
|
||||
|
||||
# Looking for Sponsors
|
||||
|
||||
I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free.
|
||||
|
||||
# License
|
||||
|
||||
MIT
|
||||
2117
vendor/github.com/goccy/go-yaml/ast/ast.go
generated
vendored
Normal file
2117
vendor/github.com/goccy/go-yaml/ast/ast.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1753
vendor/github.com/goccy/go-yaml/decode.go
generated
vendored
Normal file
1753
vendor/github.com/goccy/go-yaml/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
871
vendor/github.com/goccy/go-yaml/encode.go
generated
vendored
Normal file
871
vendor/github.com/goccy/go-yaml/encode.go
generated
vendored
Normal file
@@ -0,0 +1,871 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/internal/errors"
|
||||
"github.com/goccy/go-yaml/parser"
|
||||
"github.com/goccy/go-yaml/printer"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultIndentSpaces default number of space for indent
|
||||
DefaultIndentSpaces = 2
|
||||
)
|
||||
|
||||
// Encoder writes YAML values to an output stream.
|
||||
type Encoder struct {
|
||||
writer io.Writer
|
||||
opts []EncodeOption
|
||||
indent int
|
||||
indentSequence bool
|
||||
singleQuote bool
|
||||
isFlowStyle bool
|
||||
isJSONStyle bool
|
||||
useJSONMarshaler bool
|
||||
anchorCallback func(*ast.AnchorNode, interface{}) error
|
||||
anchorPtrToNameMap map[uintptr]string
|
||||
customMarshalerMap map[reflect.Type]func(interface{}) ([]byte, error)
|
||||
useLiteralStyleIfMultiline bool
|
||||
commentMap map[*Path][]*Comment
|
||||
written bool
|
||||
|
||||
line int
|
||||
column int
|
||||
offset int
|
||||
indentNum int
|
||||
indentLevel int
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
// The Encoder should be closed after use to flush all data to w.
|
||||
func NewEncoder(w io.Writer, opts ...EncodeOption) *Encoder {
|
||||
return &Encoder{
|
||||
writer: w,
|
||||
opts: opts,
|
||||
indent: DefaultIndentSpaces,
|
||||
anchorPtrToNameMap: map[uintptr]string{},
|
||||
customMarshalerMap: map[reflect.Type]func(interface{}) ([]byte, error){},
|
||||
line: 1,
|
||||
column: 1,
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the encoder by writing any remaining data.
|
||||
// It does not write a stream terminating string "...".
|
||||
func (e *Encoder) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode writes the YAML encoding of v to the stream.
|
||||
// If multiple items are encoded to the stream,
|
||||
// the second and subsequent document will be preceded with a "---" document separator,
|
||||
// but the first will not.
|
||||
//
|
||||
// See the documentation for Marshal for details about the conversion of Go values to YAML.
|
||||
func (e *Encoder) Encode(v interface{}) error {
|
||||
return e.EncodeContext(context.Background(), v)
|
||||
}
|
||||
|
||||
// EncodeContext writes the YAML encoding of v to the stream with context.Context.
|
||||
func (e *Encoder) EncodeContext(ctx context.Context, v interface{}) error {
|
||||
node, err := e.EncodeToNodeContext(ctx, v)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to encode to node")
|
||||
}
|
||||
if err := e.setCommentByCommentMap(node); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment by comment map")
|
||||
}
|
||||
if !e.written {
|
||||
e.written = true
|
||||
} else {
|
||||
// write document separator
|
||||
e.writer.Write([]byte("---\n"))
|
||||
}
|
||||
var p printer.Printer
|
||||
e.writer.Write(p.PrintNode(node))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeToNode convert v to ast.Node.
|
||||
func (e *Encoder) EncodeToNode(v interface{}) (ast.Node, error) {
|
||||
return e.EncodeToNodeContext(context.Background(), v)
|
||||
}
|
||||
|
||||
// EncodeToNodeContext convert v to ast.Node with context.Context.
|
||||
func (e *Encoder) EncodeToNodeContext(ctx context.Context, v interface{}) (ast.Node, error) {
|
||||
for _, opt := range e.opts {
|
||||
if err := opt(e); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to run option for encoder")
|
||||
}
|
||||
}
|
||||
node, err := e.encodeValue(ctx, reflect.ValueOf(v), 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode value")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) setCommentByCommentMap(node ast.Node) error {
|
||||
if e.commentMap == nil {
|
||||
return nil
|
||||
}
|
||||
for path, comments := range e.commentMap {
|
||||
n, err := path.FilterNode(node)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to filter node")
|
||||
}
|
||||
if n == nil {
|
||||
continue
|
||||
}
|
||||
for _, comment := range comments {
|
||||
commentTokens := []*token.Token{}
|
||||
for _, text := range comment.Texts {
|
||||
commentTokens = append(commentTokens, token.New(text, text, nil))
|
||||
}
|
||||
commentGroup := ast.CommentGroup(commentTokens)
|
||||
switch comment.Position {
|
||||
case CommentHeadPosition:
|
||||
if err := e.setHeadComment(node, n, commentGroup); err != nil {
|
||||
return errors.Wrapf(err, "failed to set head comment")
|
||||
}
|
||||
case CommentLinePosition:
|
||||
if err := e.setLineComment(node, n, commentGroup); err != nil {
|
||||
return errors.Wrapf(err, "failed to set line comment")
|
||||
}
|
||||
case CommentFootPosition:
|
||||
if err := e.setFootComment(node, n, commentGroup); err != nil {
|
||||
return errors.Wrapf(err, "failed to set foot comment")
|
||||
}
|
||||
default:
|
||||
return ErrUnknownCommentPositionType
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) setHeadComment(node ast.Node, filtered ast.Node, comment *ast.CommentGroupNode) error {
|
||||
parent := ast.Parent(node, filtered)
|
||||
if parent == nil {
|
||||
return ErrUnsupportedHeadPositionType(node)
|
||||
}
|
||||
switch p := parent.(type) {
|
||||
case *ast.MappingValueNode:
|
||||
if err := p.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment")
|
||||
}
|
||||
case *ast.MappingNode:
|
||||
if err := p.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment")
|
||||
}
|
||||
case *ast.SequenceNode:
|
||||
if len(p.ValueHeadComments) == 0 {
|
||||
p.ValueHeadComments = make([]*ast.CommentGroupNode, len(p.Values))
|
||||
}
|
||||
var foundIdx int
|
||||
for idx, v := range p.Values {
|
||||
if v == filtered {
|
||||
foundIdx = idx
|
||||
break
|
||||
}
|
||||
}
|
||||
p.ValueHeadComments[foundIdx] = comment
|
||||
default:
|
||||
return ErrUnsupportedHeadPositionType(node)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) setLineComment(node ast.Node, filtered ast.Node, comment *ast.CommentGroupNode) error {
|
||||
switch filtered.(type) {
|
||||
case *ast.MappingValueNode, *ast.SequenceNode:
|
||||
// Line comment cannot be set for mapping value node.
|
||||
// It should probably be set for the parent map node
|
||||
if err := e.setLineCommentToParentMapNode(node, filtered, comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set line comment to parent node")
|
||||
}
|
||||
default:
|
||||
if err := filtered.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) setLineCommentToParentMapNode(node ast.Node, filtered ast.Node, comment *ast.CommentGroupNode) error {
|
||||
parent := ast.Parent(node, filtered)
|
||||
if parent == nil {
|
||||
return ErrUnsupportedLinePositionType(node)
|
||||
}
|
||||
switch p := parent.(type) {
|
||||
case *ast.MappingValueNode:
|
||||
if err := p.Key.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment")
|
||||
}
|
||||
case *ast.MappingNode:
|
||||
if err := p.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment")
|
||||
}
|
||||
default:
|
||||
return ErrUnsupportedLinePositionType(parent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) setFootComment(node ast.Node, filtered ast.Node, comment *ast.CommentGroupNode) error {
|
||||
parent := ast.Parent(node, filtered)
|
||||
if parent == nil {
|
||||
return ErrUnsupportedFootPositionType(node)
|
||||
}
|
||||
switch n := parent.(type) {
|
||||
case *ast.MappingValueNode:
|
||||
n.FootComment = comment
|
||||
case *ast.MappingNode:
|
||||
n.FootComment = comment
|
||||
case *ast.SequenceNode:
|
||||
n.FootComment = comment
|
||||
default:
|
||||
return ErrUnsupportedFootPositionType(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeDocument(doc []byte) (ast.Node, error) {
|
||||
f, err := parser.ParseBytes(doc, 0)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse yaml")
|
||||
}
|
||||
for _, docNode := range f.Docs {
|
||||
if docNode.Body != nil {
|
||||
return docNode.Body, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) isInvalidValue(v reflect.Value) bool {
|
||||
if !v.IsValid() {
|
||||
return true
|
||||
}
|
||||
kind := v.Type().Kind()
|
||||
if kind == reflect.Ptr && v.IsNil() {
|
||||
return true
|
||||
}
|
||||
if kind == reflect.Interface && v.IsNil() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type jsonMarshaler interface {
|
||||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
func (e *Encoder) existsTypeInCustomMarshalerMap(t reflect.Type) bool {
|
||||
if _, exists := e.customMarshalerMap[t]; exists {
|
||||
return true
|
||||
}
|
||||
|
||||
globalCustomMarshalerMu.Lock()
|
||||
defer globalCustomMarshalerMu.Unlock()
|
||||
if _, exists := globalCustomMarshalerMap[t]; exists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) marshalerFromCustomMarshalerMap(t reflect.Type) (func(interface{}) ([]byte, error), bool) {
|
||||
if marshaler, exists := e.customMarshalerMap[t]; exists {
|
||||
return marshaler, exists
|
||||
}
|
||||
|
||||
globalCustomMarshalerMu.Lock()
|
||||
defer globalCustomMarshalerMu.Unlock()
|
||||
if marshaler, exists := globalCustomMarshalerMap[t]; exists {
|
||||
return marshaler, exists
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (e *Encoder) canEncodeByMarshaler(v reflect.Value) bool {
|
||||
if !v.CanInterface() {
|
||||
return false
|
||||
}
|
||||
if e.existsTypeInCustomMarshalerMap(v.Type()) {
|
||||
return true
|
||||
}
|
||||
iface := v.Interface()
|
||||
switch iface.(type) {
|
||||
case BytesMarshalerContext:
|
||||
return true
|
||||
case BytesMarshaler:
|
||||
return true
|
||||
case InterfaceMarshalerContext:
|
||||
return true
|
||||
case InterfaceMarshaler:
|
||||
return true
|
||||
case time.Time:
|
||||
return true
|
||||
case time.Duration:
|
||||
return true
|
||||
case encoding.TextMarshaler:
|
||||
return true
|
||||
case jsonMarshaler:
|
||||
return e.useJSONMarshaler
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column int) (ast.Node, error) {
|
||||
iface := v.Interface()
|
||||
|
||||
if marshaler, exists := e.marshalerFromCustomMarshalerMap(v.Type()); exists {
|
||||
doc, err := marshaler(iface)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalYAML")
|
||||
}
|
||||
node, err := e.encodeDocument(doc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode document")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
if marshaler, ok := iface.(BytesMarshalerContext); ok {
|
||||
doc, err := marshaler.MarshalYAML(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalYAML")
|
||||
}
|
||||
node, err := e.encodeDocument(doc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode document")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
if marshaler, ok := iface.(BytesMarshaler); ok {
|
||||
doc, err := marshaler.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalYAML")
|
||||
}
|
||||
node, err := e.encodeDocument(doc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode document")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
if marshaler, ok := iface.(InterfaceMarshalerContext); ok {
|
||||
marshalV, err := marshaler.MarshalYAML(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalYAML")
|
||||
}
|
||||
return e.encodeValue(ctx, reflect.ValueOf(marshalV), column)
|
||||
}
|
||||
|
||||
if marshaler, ok := iface.(InterfaceMarshaler); ok {
|
||||
marshalV, err := marshaler.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalYAML")
|
||||
}
|
||||
return e.encodeValue(ctx, reflect.ValueOf(marshalV), column)
|
||||
}
|
||||
|
||||
if t, ok := iface.(time.Time); ok {
|
||||
return e.encodeTime(t, column), nil
|
||||
}
|
||||
|
||||
if t, ok := iface.(time.Duration); ok {
|
||||
return e.encodeDuration(t, column), nil
|
||||
}
|
||||
|
||||
if marshaler, ok := iface.(encoding.TextMarshaler); ok {
|
||||
doc, err := marshaler.MarshalText()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalText")
|
||||
}
|
||||
node, err := e.encodeDocument(doc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode document")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
if e.useJSONMarshaler {
|
||||
if marshaler, ok := iface.(jsonMarshaler); ok {
|
||||
jsonBytes, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to MarshalJSON")
|
||||
}
|
||||
doc, err := JSONToYAML(jsonBytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to convert json to yaml")
|
||||
}
|
||||
node, err := e.encodeDocument(doc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode document")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, xerrors.Errorf("does not implemented Marshaler")
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeValue(ctx context.Context, v reflect.Value, column int) (ast.Node, error) {
|
||||
if e.isInvalidValue(v) {
|
||||
return e.encodeNil(), nil
|
||||
}
|
||||
if e.canEncodeByMarshaler(v) {
|
||||
node, err := e.encodeByMarshaler(ctx, v, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode by marshaler")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return e.encodeInt(v.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return e.encodeUint(v.Uint()), nil
|
||||
case reflect.Float32:
|
||||
return e.encodeFloat(v.Float(), 32), nil
|
||||
case reflect.Float64:
|
||||
return e.encodeFloat(v.Float(), 64), nil
|
||||
case reflect.Ptr:
|
||||
anchorName := e.anchorPtrToNameMap[v.Pointer()]
|
||||
if anchorName != "" {
|
||||
aliasName := anchorName
|
||||
alias := ast.Alias(token.New("*", "*", e.pos(column)))
|
||||
alias.Value = ast.String(token.New(aliasName, aliasName, e.pos(column)))
|
||||
return alias, nil
|
||||
}
|
||||
return e.encodeValue(ctx, v.Elem(), column)
|
||||
case reflect.Interface:
|
||||
return e.encodeValue(ctx, v.Elem(), column)
|
||||
case reflect.String:
|
||||
return e.encodeString(v.String(), column), nil
|
||||
case reflect.Bool:
|
||||
return e.encodeBool(v.Bool()), nil
|
||||
case reflect.Slice:
|
||||
if mapSlice, ok := v.Interface().(MapSlice); ok {
|
||||
return e.encodeMapSlice(ctx, mapSlice, column)
|
||||
}
|
||||
return e.encodeSlice(ctx, v)
|
||||
case reflect.Array:
|
||||
return e.encodeArray(ctx, v)
|
||||
case reflect.Struct:
|
||||
if v.CanInterface() {
|
||||
if mapItem, ok := v.Interface().(MapItem); ok {
|
||||
return e.encodeMapItem(ctx, mapItem, column)
|
||||
}
|
||||
if t, ok := v.Interface().(time.Time); ok {
|
||||
return e.encodeTime(t, column), nil
|
||||
}
|
||||
}
|
||||
return e.encodeStruct(ctx, v, column)
|
||||
case reflect.Map:
|
||||
return e.encodeMap(ctx, v, column), nil
|
||||
default:
|
||||
return nil, xerrors.Errorf("unknown value type %s", v.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) pos(column int) *token.Position {
|
||||
return &token.Position{
|
||||
Line: e.line,
|
||||
Column: column,
|
||||
Offset: e.offset,
|
||||
IndentNum: e.indentNum,
|
||||
IndentLevel: e.indentLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeNil() *ast.NullNode {
|
||||
value := "null"
|
||||
return ast.Null(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeInt(v int64) *ast.IntegerNode {
|
||||
value := fmt.Sprint(v)
|
||||
return ast.Integer(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeUint(v uint64) *ast.IntegerNode {
|
||||
value := fmt.Sprint(v)
|
||||
return ast.Integer(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeFloat(v float64, bitSize int) ast.Node {
|
||||
if v == math.Inf(0) {
|
||||
value := ".inf"
|
||||
return ast.Infinity(token.New(value, value, e.pos(e.column)))
|
||||
} else if v == math.Inf(-1) {
|
||||
value := "-.inf"
|
||||
return ast.Infinity(token.New(value, value, e.pos(e.column)))
|
||||
} else if math.IsNaN(v) {
|
||||
value := ".nan"
|
||||
return ast.Nan(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
value := strconv.FormatFloat(v, 'g', -1, bitSize)
|
||||
if !strings.Contains(value, ".") && !strings.Contains(value, "e") {
|
||||
// append x.0 suffix to keep float value context
|
||||
value = fmt.Sprintf("%s.0", value)
|
||||
}
|
||||
return ast.Float(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) isNeedQuoted(v string) bool {
|
||||
if e.isJSONStyle {
|
||||
return true
|
||||
}
|
||||
if e.useLiteralStyleIfMultiline && strings.ContainsAny(v, "\n\r") {
|
||||
return false
|
||||
}
|
||||
if e.isFlowStyle && strings.ContainsAny(v, `]},'"`) {
|
||||
return true
|
||||
}
|
||||
if token.IsNeedQuoted(v) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeString(v string, column int) *ast.StringNode {
|
||||
if e.isNeedQuoted(v) {
|
||||
if e.singleQuote {
|
||||
v = quoteWith(v, '\'')
|
||||
} else {
|
||||
v = strconv.Quote(v)
|
||||
}
|
||||
}
|
||||
return ast.String(token.New(v, v, e.pos(column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeBool(v bool) *ast.BoolNode {
|
||||
value := fmt.Sprint(v)
|
||||
return ast.Bool(token.New(value, value, e.pos(e.column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
|
||||
if e.indentSequence {
|
||||
e.column += e.indent
|
||||
}
|
||||
column := e.column
|
||||
sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
node, err := e.encodeValue(ctx, value.Index(i), column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode value for slice")
|
||||
}
|
||||
sequence.Values = append(sequence.Values, node)
|
||||
}
|
||||
if e.indentSequence {
|
||||
e.column -= e.indent
|
||||
}
|
||||
return sequence, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeArray(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
|
||||
if e.indentSequence {
|
||||
e.column += e.indent
|
||||
}
|
||||
column := e.column
|
||||
sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
node, err := e.encodeValue(ctx, value.Index(i), column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode value for array")
|
||||
}
|
||||
sequence.Values = append(sequence.Values, node)
|
||||
}
|
||||
if e.indentSequence {
|
||||
e.column -= e.indent
|
||||
}
|
||||
return sequence, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeMapItem(ctx context.Context, item MapItem, column int) (*ast.MappingValueNode, error) {
|
||||
k := reflect.ValueOf(item.Key)
|
||||
v := reflect.ValueOf(item.Value)
|
||||
value, err := e.encodeValue(ctx, v, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode MapItem")
|
||||
}
|
||||
if e.isMapNode(value) {
|
||||
value.AddColumn(e.indent)
|
||||
}
|
||||
return ast.MappingValue(
|
||||
token.New("", "", e.pos(column)),
|
||||
e.encodeString(k.Interface().(string), column),
|
||||
value,
|
||||
), nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeMapSlice(ctx context.Context, value MapSlice, column int) (*ast.MappingNode, error) {
|
||||
node := ast.Mapping(token.New("", "", e.pos(column)), e.isFlowStyle)
|
||||
for _, item := range value {
|
||||
value, err := e.encodeMapItem(ctx, item, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode MapItem for MapSlice")
|
||||
}
|
||||
node.Values = append(node.Values, value)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) isMapNode(node ast.Node) bool {
|
||||
_, ok := node.(ast.MapNode)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeMap(ctx context.Context, value reflect.Value, column int) ast.Node {
|
||||
node := ast.Mapping(token.New("", "", e.pos(column)), e.isFlowStyle)
|
||||
keys := make([]interface{}, len(value.MapKeys()))
|
||||
for i, k := range value.MapKeys() {
|
||||
keys[i] = k.Interface()
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return fmt.Sprint(keys[i]) < fmt.Sprint(keys[j])
|
||||
})
|
||||
for _, key := range keys {
|
||||
k := reflect.ValueOf(key)
|
||||
v := value.MapIndex(k)
|
||||
value, err := e.encodeValue(ctx, v, column)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if e.isMapNode(value) {
|
||||
value.AddColumn(e.indent)
|
||||
}
|
||||
node.Values = append(node.Values, ast.MappingValue(
|
||||
nil,
|
||||
e.encodeString(fmt.Sprint(key), column),
|
||||
value,
|
||||
))
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// IsZeroer is used to check whether an object is zero to determine
|
||||
// whether it should be omitted when marshaling with the omitempty flag.
|
||||
// One notable implementation is time.Time.
|
||||
type IsZeroer interface {
|
||||
IsZero() bool
|
||||
}
|
||||
|
||||
func (e *Encoder) isZeroValue(v reflect.Value) bool {
|
||||
kind := v.Kind()
|
||||
if z, ok := v.Interface().(IsZeroer); ok {
|
||||
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
|
||||
return true
|
||||
}
|
||||
return z.IsZero()
|
||||
}
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
return len(v.String()) == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Slice:
|
||||
return v.Len() == 0
|
||||
case reflect.Map:
|
||||
return v.Len() == 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Struct:
|
||||
vt := v.Type()
|
||||
for i := v.NumField() - 1; i >= 0; i-- {
|
||||
if vt.Field(i).PkgPath != "" {
|
||||
continue // private field
|
||||
}
|
||||
if !e.isZeroValue(v.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTime(v time.Time, column int) *ast.StringNode {
|
||||
value := v.Format(time.RFC3339Nano)
|
||||
if e.isJSONStyle {
|
||||
value = strconv.Quote(value)
|
||||
}
|
||||
return ast.String(token.New(value, value, e.pos(column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeDuration(v time.Duration, column int) *ast.StringNode {
|
||||
value := v.String()
|
||||
if e.isJSONStyle {
|
||||
value = strconv.Quote(value)
|
||||
}
|
||||
return ast.String(token.New(value, value, e.pos(column)))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeAnchor(anchorName string, value ast.Node, fieldValue reflect.Value, column int) (*ast.AnchorNode, error) {
|
||||
anchorNode := ast.Anchor(token.New("&", "&", e.pos(column)))
|
||||
anchorNode.Name = ast.String(token.New(anchorName, anchorName, e.pos(column)))
|
||||
anchorNode.Value = value
|
||||
if e.anchorCallback != nil {
|
||||
if err := e.anchorCallback(anchorNode, fieldValue.Interface()); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal anchor")
|
||||
}
|
||||
if snode, ok := anchorNode.Name.(*ast.StringNode); ok {
|
||||
anchorName = snode.Value
|
||||
}
|
||||
}
|
||||
if fieldValue.Kind() == reflect.Ptr {
|
||||
e.anchorPtrToNameMap[fieldValue.Pointer()] = anchorName
|
||||
}
|
||||
return anchorNode, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column int) (ast.Node, error) {
|
||||
node := ast.Mapping(token.New("", "", e.pos(column)), e.isFlowStyle)
|
||||
structType := value.Type()
|
||||
structFieldMap, err := structFieldMap(structType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get struct field map")
|
||||
}
|
||||
hasInlineAnchorField := false
|
||||
var inlineAnchorValue reflect.Value
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
field := structType.Field(i)
|
||||
if isIgnoredStructField(field) {
|
||||
continue
|
||||
}
|
||||
fieldValue := value.FieldByName(field.Name)
|
||||
structField := structFieldMap[field.Name]
|
||||
if structField.IsOmitEmpty && e.isZeroValue(fieldValue) {
|
||||
// omit encoding
|
||||
continue
|
||||
}
|
||||
ve := e
|
||||
if !e.isFlowStyle && structField.IsFlow {
|
||||
ve = &Encoder{}
|
||||
*ve = *e
|
||||
ve.isFlowStyle = true
|
||||
}
|
||||
value, err := ve.encodeValue(ctx, fieldValue, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode value")
|
||||
}
|
||||
if e.isMapNode(value) {
|
||||
value.AddColumn(e.indent)
|
||||
}
|
||||
var key ast.MapKeyNode = e.encodeString(structField.RenderName, column)
|
||||
switch {
|
||||
case structField.AnchorName != "":
|
||||
anchorNode, err := e.encodeAnchor(structField.AnchorName, value, fieldValue, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode anchor")
|
||||
}
|
||||
value = anchorNode
|
||||
case structField.IsAutoAlias:
|
||||
if fieldValue.Kind() != reflect.Ptr {
|
||||
return nil, xerrors.Errorf(
|
||||
"%s in struct is not pointer type. but required automatically alias detection",
|
||||
structField.FieldName,
|
||||
)
|
||||
}
|
||||
anchorName := e.anchorPtrToNameMap[fieldValue.Pointer()]
|
||||
if anchorName == "" {
|
||||
return nil, xerrors.Errorf(
|
||||
"cannot find anchor name from pointer address for automatically alias detection",
|
||||
)
|
||||
}
|
||||
aliasName := anchorName
|
||||
alias := ast.Alias(token.New("*", "*", e.pos(column)))
|
||||
alias.Value = ast.String(token.New(aliasName, aliasName, e.pos(column)))
|
||||
value = alias
|
||||
if structField.IsInline {
|
||||
// if both used alias and inline, output `<<: *alias`
|
||||
key = ast.MergeKey(token.New("<<", "<<", e.pos(column)))
|
||||
}
|
||||
case structField.AliasName != "":
|
||||
aliasName := structField.AliasName
|
||||
alias := ast.Alias(token.New("*", "*", e.pos(column)))
|
||||
alias.Value = ast.String(token.New(aliasName, aliasName, e.pos(column)))
|
||||
value = alias
|
||||
if structField.IsInline {
|
||||
// if both used alias and inline, output `<<: *alias`
|
||||
key = ast.MergeKey(token.New("<<", "<<", e.pos(column)))
|
||||
}
|
||||
case structField.IsInline:
|
||||
isAutoAnchor := structField.IsAutoAnchor
|
||||
if !hasInlineAnchorField {
|
||||
hasInlineAnchorField = isAutoAnchor
|
||||
}
|
||||
if isAutoAnchor {
|
||||
inlineAnchorValue = fieldValue
|
||||
}
|
||||
mapNode, ok := value.(ast.MapNode)
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("inline value is must be map or struct type")
|
||||
}
|
||||
mapIter := mapNode.MapRange()
|
||||
for mapIter.Next() {
|
||||
key := mapIter.Key()
|
||||
value := mapIter.Value()
|
||||
keyName := key.GetToken().Value
|
||||
if structFieldMap.isIncludedRenderName(keyName) {
|
||||
// if declared same key name, skip encoding this field
|
||||
continue
|
||||
}
|
||||
key.AddColumn(-e.indent)
|
||||
value.AddColumn(-e.indent)
|
||||
node.Values = append(node.Values, ast.MappingValue(nil, key, value))
|
||||
}
|
||||
continue
|
||||
case structField.IsAutoAnchor:
|
||||
anchorNode, err := e.encodeAnchor(structField.RenderName, value, fieldValue, column)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to encode anchor")
|
||||
}
|
||||
value = anchorNode
|
||||
}
|
||||
node.Values = append(node.Values, ast.MappingValue(nil, key, value))
|
||||
}
|
||||
if hasInlineAnchorField {
|
||||
node.AddColumn(e.indent)
|
||||
anchorName := "anchor"
|
||||
anchorNode := ast.Anchor(token.New("&", "&", e.pos(column)))
|
||||
anchorNode.Name = ast.String(token.New(anchorName, anchorName, e.pos(column)))
|
||||
anchorNode.Value = node
|
||||
if e.anchorCallback != nil {
|
||||
if err := e.anchorCallback(anchorNode, value.Addr().Interface()); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal anchor")
|
||||
}
|
||||
if snode, ok := anchorNode.Name.(*ast.StringNode); ok {
|
||||
anchorName = snode.Value
|
||||
}
|
||||
}
|
||||
if inlineAnchorValue.Kind() == reflect.Ptr {
|
||||
e.anchorPtrToNameMap[inlineAnchorValue.Pointer()] = anchorName
|
||||
}
|
||||
return anchorNode, nil
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
62
vendor/github.com/goccy/go-yaml/error.go
generated
vendored
Normal file
62
vendor/github.com/goccy/go-yaml/error.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidQuery = xerrors.New("invalid query")
|
||||
ErrInvalidPath = xerrors.New("invalid path instance")
|
||||
ErrInvalidPathString = xerrors.New("invalid path string")
|
||||
ErrNotFoundNode = xerrors.New("node not found")
|
||||
ErrUnknownCommentPositionType = xerrors.New("unknown comment position type")
|
||||
ErrInvalidCommentMapValue = xerrors.New("invalid comment map value. it must be not nil value")
|
||||
)
|
||||
|
||||
func ErrUnsupportedHeadPositionType(node ast.Node) error {
|
||||
return xerrors.Errorf("unsupported comment head position for %s", node.Type())
|
||||
}
|
||||
|
||||
func ErrUnsupportedLinePositionType(node ast.Node) error {
|
||||
return xerrors.Errorf("unsupported comment line position for %s", node.Type())
|
||||
}
|
||||
|
||||
func ErrUnsupportedFootPositionType(node ast.Node) error {
|
||||
return xerrors.Errorf("unsupported comment foot position for %s", node.Type())
|
||||
}
|
||||
|
||||
// IsInvalidQueryError whether err is ErrInvalidQuery or not.
|
||||
func IsInvalidQueryError(err error) bool {
|
||||
return xerrors.Is(err, ErrInvalidQuery)
|
||||
}
|
||||
|
||||
// IsInvalidPathError whether err is ErrInvalidPath or not.
|
||||
func IsInvalidPathError(err error) bool {
|
||||
return xerrors.Is(err, ErrInvalidPath)
|
||||
}
|
||||
|
||||
// IsInvalidPathStringError whether err is ErrInvalidPathString or not.
|
||||
func IsInvalidPathStringError(err error) bool {
|
||||
return xerrors.Is(err, ErrInvalidPathString)
|
||||
}
|
||||
|
||||
// IsNotFoundNodeError whether err is ErrNotFoundNode or not.
|
||||
func IsNotFoundNodeError(err error) bool {
|
||||
return xerrors.Is(err, ErrNotFoundNode)
|
||||
}
|
||||
|
||||
// IsInvalidTokenTypeError whether err is ast.ErrInvalidTokenType or not.
|
||||
func IsInvalidTokenTypeError(err error) bool {
|
||||
return xerrors.Is(err, ast.ErrInvalidTokenType)
|
||||
}
|
||||
|
||||
// IsInvalidAnchorNameError whether err is ast.ErrInvalidAnchorName or not.
|
||||
func IsInvalidAnchorNameError(err error) bool {
|
||||
return xerrors.Is(err, ast.ErrInvalidAnchorName)
|
||||
}
|
||||
|
||||
// IsInvalidAliasNameError whether err is ast.ErrInvalidAliasName or not.
|
||||
func IsInvalidAliasNameError(err error) bool {
|
||||
return xerrors.Is(err, ast.ErrInvalidAliasName)
|
||||
}
|
||||
260
vendor/github.com/goccy/go-yaml/internal/errors/error.go
generated
vendored
Normal file
260
vendor/github.com/goccy/go-yaml/internal/errors/error.go
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-yaml/printer"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultColorize = false
|
||||
defaultIncludeSource = true
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDecodeRequiredPointerType = xerrors.New("required pointer type value")
|
||||
)
|
||||
|
||||
// Wrapf wrap error for stack trace
|
||||
func Wrapf(err error, msg string, args ...interface{}) error {
|
||||
return &wrapError{
|
||||
baseError: &baseError{},
|
||||
err: xerrors.Errorf(msg, args...),
|
||||
nextErr: err,
|
||||
frame: xerrors.Caller(1),
|
||||
}
|
||||
}
|
||||
|
||||
// ErrSyntax create syntax error instance with message and token
|
||||
func ErrSyntax(msg string, tk *token.Token) *syntaxError {
|
||||
return &syntaxError{
|
||||
baseError: &baseError{},
|
||||
msg: msg,
|
||||
token: tk,
|
||||
frame: xerrors.Caller(1),
|
||||
}
|
||||
}
|
||||
|
||||
type baseError struct {
|
||||
state fmt.State
|
||||
verb rune
|
||||
}
|
||||
|
||||
func (e *baseError) Error() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *baseError) chainStateAndVerb(err error) {
|
||||
wrapErr, ok := err.(*wrapError)
|
||||
if ok {
|
||||
wrapErr.state = e.state
|
||||
wrapErr.verb = e.verb
|
||||
}
|
||||
syntaxErr, ok := err.(*syntaxError)
|
||||
if ok {
|
||||
syntaxErr.state = e.state
|
||||
syntaxErr.verb = e.verb
|
||||
}
|
||||
}
|
||||
|
||||
type wrapError struct {
|
||||
*baseError
|
||||
err error
|
||||
nextErr error
|
||||
frame xerrors.Frame
|
||||
}
|
||||
|
||||
type FormatErrorPrinter struct {
|
||||
xerrors.Printer
|
||||
Colored bool
|
||||
InclSource bool
|
||||
}
|
||||
|
||||
func (e *wrapError) As(target interface{}) bool {
|
||||
err := e.nextErr
|
||||
for {
|
||||
if wrapErr, ok := err.(*wrapError); ok {
|
||||
err = wrapErr.nextErr
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return xerrors.As(err, target)
|
||||
}
|
||||
|
||||
func (e *wrapError) Unwrap() error {
|
||||
return e.nextErr
|
||||
}
|
||||
|
||||
func (e *wrapError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
|
||||
return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
|
||||
}
|
||||
|
||||
func (e *wrapError) FormatError(p xerrors.Printer) error {
|
||||
if _, ok := p.(*FormatErrorPrinter); !ok {
|
||||
p = &FormatErrorPrinter{
|
||||
Printer: p,
|
||||
Colored: defaultColorize,
|
||||
InclSource: defaultIncludeSource,
|
||||
}
|
||||
}
|
||||
if e.verb == 'v' && e.state.Flag('+') {
|
||||
// print stack trace for debugging
|
||||
p.Print(e.err, "\n")
|
||||
e.frame.Format(p)
|
||||
e.chainStateAndVerb(e.nextErr)
|
||||
return e.nextErr
|
||||
}
|
||||
err := e.nextErr
|
||||
for {
|
||||
if wrapErr, ok := err.(*wrapError); ok {
|
||||
err = wrapErr.nextErr
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
e.chainStateAndVerb(err)
|
||||
if fmtErr, ok := err.(xerrors.Formatter); ok {
|
||||
fmtErr.FormatError(p)
|
||||
} else {
|
||||
p.Print(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type wrapState struct {
|
||||
org fmt.State
|
||||
}
|
||||
|
||||
func (s *wrapState) Write(b []byte) (n int, err error) {
|
||||
return s.org.Write(b)
|
||||
}
|
||||
|
||||
func (s *wrapState) Width() (wid int, ok bool) {
|
||||
return s.org.Width()
|
||||
}
|
||||
|
||||
func (s *wrapState) Precision() (prec int, ok bool) {
|
||||
return s.org.Precision()
|
||||
}
|
||||
|
||||
func (s *wrapState) Flag(c int) bool {
|
||||
// set true to 'printDetail' forced because when p.Detail() is false, xerrors.Printer no output any text
|
||||
if c == '#' {
|
||||
// ignore '#' keyword because xerrors.FormatError doesn't set true to printDetail.
|
||||
// ( see https://github.com/golang/xerrors/blob/master/adaptor.go#L39-L43 )
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (e *wrapError) Format(state fmt.State, verb rune) {
|
||||
e.state = state
|
||||
e.verb = verb
|
||||
xerrors.FormatError(e, &wrapState{org: state}, verb)
|
||||
}
|
||||
|
||||
func (e *wrapError) Error() string {
|
||||
var buf bytes.Buffer
|
||||
e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type syntaxError struct {
|
||||
*baseError
|
||||
msg string
|
||||
token *token.Token
|
||||
frame xerrors.Frame
|
||||
}
|
||||
|
||||
func (e *syntaxError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
|
||||
return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
|
||||
}
|
||||
|
||||
func (e *syntaxError) FormatError(p xerrors.Printer) error {
|
||||
var pp printer.Printer
|
||||
|
||||
var colored, inclSource bool
|
||||
if fep, ok := p.(*FormatErrorPrinter); ok {
|
||||
colored = fep.Colored
|
||||
inclSource = fep.InclSource
|
||||
}
|
||||
|
||||
pos := fmt.Sprintf("[%d:%d] ", e.token.Position.Line, e.token.Position.Column)
|
||||
msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.msg), colored)
|
||||
if inclSource {
|
||||
msg += "\n" + pp.PrintErrorToken(e.token, colored)
|
||||
}
|
||||
p.Print(msg)
|
||||
|
||||
if e.verb == 'v' && e.state.Flag('+') {
|
||||
// %+v
|
||||
// print stack trace for debugging
|
||||
e.frame.Format(p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PrettyPrinter interface {
|
||||
PrettyPrint(xerrors.Printer, bool, bool) error
|
||||
}
|
||||
type Sink struct{ *bytes.Buffer }
|
||||
|
||||
func (es *Sink) Print(args ...interface{}) {
|
||||
fmt.Fprint(es.Buffer, args...)
|
||||
}
|
||||
|
||||
func (es *Sink) Printf(f string, args ...interface{}) {
|
||||
fmt.Fprintf(es.Buffer, f, args...)
|
||||
}
|
||||
|
||||
func (es *Sink) Detail() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *syntaxError) Error() string {
|
||||
var buf bytes.Buffer
|
||||
e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type TypeError struct {
|
||||
DstType reflect.Type
|
||||
SrcType reflect.Type
|
||||
StructFieldName *string
|
||||
Token *token.Token
|
||||
}
|
||||
|
||||
func (e *TypeError) Error() string {
|
||||
if e.StructFieldName != nil {
|
||||
return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.SrcType, *e.StructFieldName, e.DstType)
|
||||
}
|
||||
return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.SrcType, e.DstType)
|
||||
}
|
||||
|
||||
func (e *TypeError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
|
||||
return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
|
||||
}
|
||||
|
||||
func (e *TypeError) FormatError(p xerrors.Printer) error {
|
||||
var pp printer.Printer
|
||||
|
||||
var colored, inclSource bool
|
||||
if fep, ok := p.(*FormatErrorPrinter); ok {
|
||||
colored = fep.Colored
|
||||
inclSource = fep.InclSource
|
||||
}
|
||||
|
||||
pos := fmt.Sprintf("[%d:%d] ", e.Token.Position.Line, e.Token.Position.Column)
|
||||
msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.Error()), colored)
|
||||
if inclSource {
|
||||
msg += "\n" + pp.PrintErrorToken(e.Token, colored)
|
||||
}
|
||||
p.Print(msg)
|
||||
|
||||
return nil
|
||||
}
|
||||
23
vendor/github.com/goccy/go-yaml/lexer/lexer.go
generated
vendored
Normal file
23
vendor/github.com/goccy/go-yaml/lexer/lexer.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/goccy/go-yaml/scanner"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
// Tokenize split to token instances from string
|
||||
func Tokenize(src string) token.Tokens {
|
||||
var s scanner.Scanner
|
||||
s.Init(src)
|
||||
var tokens token.Tokens
|
||||
for {
|
||||
subTokens, err := s.Scan()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
tokens.Add(subTokens...)
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
278
vendor/github.com/goccy/go-yaml/option.go
generated
vendored
Normal file
278
vendor/github.com/goccy/go-yaml/option.go
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
)
|
||||
|
||||
// DecodeOption functional option type for Decoder
|
||||
type DecodeOption func(d *Decoder) error
|
||||
|
||||
// ReferenceReaders pass to Decoder that reference to anchor defined by passed readers
|
||||
func ReferenceReaders(readers ...io.Reader) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.referenceReaders = append(d.referenceReaders, readers...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ReferenceFiles pass to Decoder that reference to anchor defined by passed files
|
||||
func ReferenceFiles(files ...string) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.referenceFiles = files
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ReferenceDirs pass to Decoder that reference to anchor defined by files under the passed dirs
|
||||
func ReferenceDirs(dirs ...string) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.referenceDirs = dirs
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// RecursiveDir search yaml file recursively from passed dirs by ReferenceDirs option
|
||||
func RecursiveDir(isRecursive bool) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.isRecursiveDir = isRecursive
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Validator set StructValidator instance to Decoder
|
||||
func Validator(v StructValidator) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.validator = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Strict enable DisallowUnknownField and DisallowDuplicateKey
|
||||
func Strict() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.disallowUnknownField = true
|
||||
d.disallowDuplicateKey = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DisallowUnknownField causes the Decoder to return an error when the destination
|
||||
// is a struct and the input contains object keys which do not match any
|
||||
// non-ignored, exported fields in the destination.
|
||||
func DisallowUnknownField() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.disallowUnknownField = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DisallowDuplicateKey causes an error when mapping keys that are duplicates
|
||||
func DisallowDuplicateKey() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.disallowDuplicateKey = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// UseOrderedMap can be interpreted as a map,
|
||||
// and uses MapSlice ( ordered map ) aggressively if there is no type specification
|
||||
func UseOrderedMap() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.useOrderedMap = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// UseJSONUnmarshaler if neither `BytesUnmarshaler` nor `InterfaceUnmarshaler` is implemented
|
||||
// and `UnmashalJSON([]byte)error` is implemented, convert the argument from `YAML` to `JSON` and then call it.
|
||||
func UseJSONUnmarshaler() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.useJSONUnmarshaler = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CustomUnmarshaler overrides any decoding process for the type specified in generics.
|
||||
//
|
||||
// NOTE: If RegisterCustomUnmarshaler and CustomUnmarshaler of DecodeOption are specified for the same type,
|
||||
// the CustomUnmarshaler specified in DecodeOption takes precedence.
|
||||
func CustomUnmarshaler[T any](unmarshaler func(*T, []byte) error) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
var typ *T
|
||||
d.customUnmarshalerMap[reflect.TypeOf(typ)] = func(v interface{}, b []byte) error {
|
||||
return unmarshaler(v.(*T), b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeOption functional option type for Encoder
|
||||
type EncodeOption func(e *Encoder) error
|
||||
|
||||
// Indent change indent number
|
||||
func Indent(spaces int) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.indent = spaces
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// IndentSequence causes sequence values to be indented the same value as Indent
|
||||
func IndentSequence(indent bool) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.indentSequence = indent
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// UseSingleQuote determines if single or double quotes should be preferred for strings.
|
||||
func UseSingleQuote(sq bool) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.singleQuote = sq
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Flow encoding by flow style
|
||||
func Flow(isFlowStyle bool) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.isFlowStyle = isFlowStyle
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// UseLiteralStyleIfMultiline causes encoding multiline strings with a literal syntax,
|
||||
// no matter what characters they include
|
||||
func UseLiteralStyleIfMultiline(useLiteralStyleIfMultiline bool) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.useLiteralStyleIfMultiline = useLiteralStyleIfMultiline
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// JSON encode in JSON format
|
||||
func JSON() EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.isJSONStyle = true
|
||||
e.isFlowStyle = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalAnchor call back if encoder find an anchor during encoding
|
||||
func MarshalAnchor(callback func(*ast.AnchorNode, interface{}) error) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.anchorCallback = callback
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// UseJSONMarshaler if neither `BytesMarshaler` nor `InterfaceMarshaler`
|
||||
// nor `encoding.TextMarshaler` is implemented and `MarshalJSON()([]byte, error)` is implemented,
|
||||
// call `MarshalJSON` to convert the returned `JSON` to `YAML` for processing.
|
||||
func UseJSONMarshaler() EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
e.useJSONMarshaler = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CustomMarshaler overrides any encoding process for the type specified in generics.
|
||||
//
|
||||
// NOTE: If type T implements MarshalYAML for pointer receiver, the type specified in CustomMarshaler must be *T.
|
||||
// If RegisterCustomMarshaler and CustomMarshaler of EncodeOption are specified for the same type,
|
||||
// the CustomMarshaler specified in EncodeOption takes precedence.
|
||||
func CustomMarshaler[T any](marshaler func(T) ([]byte, error)) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
var typ T
|
||||
e.customMarshalerMap[reflect.TypeOf(typ)] = func(v interface{}) ([]byte, error) {
|
||||
return marshaler(v.(T))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CommentPosition type of the position for comment.
|
||||
type CommentPosition int
|
||||
|
||||
const (
|
||||
CommentHeadPosition CommentPosition = CommentPosition(iota)
|
||||
CommentLinePosition
|
||||
CommentFootPosition
|
||||
)
|
||||
|
||||
func (p CommentPosition) String() string {
|
||||
switch p {
|
||||
case CommentHeadPosition:
|
||||
return "Head"
|
||||
case CommentLinePosition:
|
||||
return "Line"
|
||||
case CommentFootPosition:
|
||||
return "Foot"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// LineComment create a one-line comment for CommentMap.
|
||||
func LineComment(text string) *Comment {
|
||||
return &Comment{
|
||||
Texts: []string{text},
|
||||
Position: CommentLinePosition,
|
||||
}
|
||||
}
|
||||
|
||||
// HeadComment create a multiline comment for CommentMap.
|
||||
func HeadComment(texts ...string) *Comment {
|
||||
return &Comment{
|
||||
Texts: texts,
|
||||
Position: CommentHeadPosition,
|
||||
}
|
||||
}
|
||||
|
||||
// FootComment create a multiline comment for CommentMap.
|
||||
func FootComment(texts ...string) *Comment {
|
||||
return &Comment{
|
||||
Texts: texts,
|
||||
Position: CommentFootPosition,
|
||||
}
|
||||
}
|
||||
|
||||
// Comment raw data for comment.
|
||||
type Comment struct {
|
||||
Texts []string
|
||||
Position CommentPosition
|
||||
}
|
||||
|
||||
// CommentMap map of the position of the comment and the comment information.
|
||||
type CommentMap map[string][]*Comment
|
||||
|
||||
// WithComment add a comment using the location and text information given in the CommentMap.
|
||||
func WithComment(cm CommentMap) EncodeOption {
|
||||
return func(e *Encoder) error {
|
||||
commentMap := map[*Path][]*Comment{}
|
||||
for k, v := range cm {
|
||||
path, err := PathString(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commentMap[path] = v
|
||||
}
|
||||
e.commentMap = commentMap
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CommentToMap apply the position and content of comments in a YAML document to a CommentMap.
|
||||
func CommentToMap(cm CommentMap) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
if cm == nil {
|
||||
return ErrInvalidCommentMapValue
|
||||
}
|
||||
d.toCommentMap = cm
|
||||
return nil
|
||||
}
|
||||
}
|
||||
199
vendor/github.com/goccy/go-yaml/parser/context.go
generated
vendored
Normal file
199
vendor/github.com/goccy/go-yaml/parser/context.go
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
// context context at parsing
|
||||
type context struct {
|
||||
parent *context
|
||||
idx int
|
||||
size int
|
||||
tokens token.Tokens
|
||||
mode Mode
|
||||
path string
|
||||
}
|
||||
|
||||
var pathSpecialChars = []string{
|
||||
"$", "*", ".", "[", "]",
|
||||
}
|
||||
|
||||
func containsPathSpecialChar(path string) bool {
|
||||
for _, char := range pathSpecialChars {
|
||||
if strings.Contains(path, char) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func normalizePath(path string) string {
|
||||
if containsPathSpecialChar(path) {
|
||||
return fmt.Sprintf("'%s'", path)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func (c *context) withChild(path string) *context {
|
||||
ctx := c.copy()
|
||||
path = normalizePath(path)
|
||||
ctx.path += fmt.Sprintf(".%s", path)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (c *context) withIndex(idx uint) *context {
|
||||
ctx := c.copy()
|
||||
ctx.path += fmt.Sprintf("[%d]", idx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (c *context) copy() *context {
|
||||
return &context{
|
||||
parent: c,
|
||||
idx: c.idx,
|
||||
size: c.size,
|
||||
tokens: append(token.Tokens{}, c.tokens...),
|
||||
mode: c.mode,
|
||||
path: c.path,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) next() bool {
|
||||
return c.idx < c.size
|
||||
}
|
||||
|
||||
func (c *context) previousToken() *token.Token {
|
||||
if c.idx > 0 {
|
||||
return c.tokens[c.idx-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) insertToken(idx int, tk *token.Token) {
|
||||
if c.parent != nil {
|
||||
c.parent.insertToken(idx, tk)
|
||||
}
|
||||
if c.size < idx {
|
||||
return
|
||||
}
|
||||
if c.size == idx {
|
||||
curToken := c.tokens[c.size-1]
|
||||
tk.Next = curToken
|
||||
curToken.Prev = tk
|
||||
|
||||
c.tokens = append(c.tokens, tk)
|
||||
c.size = len(c.tokens)
|
||||
return
|
||||
}
|
||||
|
||||
curToken := c.tokens[idx]
|
||||
tk.Next = curToken
|
||||
curToken.Prev = tk
|
||||
|
||||
c.tokens = append(c.tokens[:idx+1], c.tokens[idx:]...)
|
||||
c.tokens[idx] = tk
|
||||
c.size = len(c.tokens)
|
||||
}
|
||||
|
||||
func (c *context) currentToken() *token.Token {
|
||||
if c.idx >= c.size {
|
||||
return nil
|
||||
}
|
||||
return c.tokens[c.idx]
|
||||
}
|
||||
|
||||
func (c *context) nextToken() *token.Token {
|
||||
if c.idx+1 >= c.size {
|
||||
return nil
|
||||
}
|
||||
return c.tokens[c.idx+1]
|
||||
}
|
||||
|
||||
func (c *context) afterNextToken() *token.Token {
|
||||
if c.idx+2 >= c.size {
|
||||
return nil
|
||||
}
|
||||
return c.tokens[c.idx+2]
|
||||
}
|
||||
|
||||
func (c *context) nextNotCommentToken() *token.Token {
|
||||
for i := c.idx + 1; i < c.size; i++ {
|
||||
tk := c.tokens[i]
|
||||
if tk.Type == token.CommentType {
|
||||
continue
|
||||
}
|
||||
return tk
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) afterNextNotCommentToken() *token.Token {
|
||||
notCommentTokenCount := 0
|
||||
for i := c.idx + 1; i < c.size; i++ {
|
||||
tk := c.tokens[i]
|
||||
if tk.Type == token.CommentType {
|
||||
continue
|
||||
}
|
||||
notCommentTokenCount++
|
||||
if notCommentTokenCount == 2 {
|
||||
return tk
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) enabledComment() bool {
|
||||
return c.mode&ParseComments != 0
|
||||
}
|
||||
|
||||
func (c *context) isCurrentCommentToken() bool {
|
||||
tk := c.currentToken()
|
||||
if tk == nil {
|
||||
return false
|
||||
}
|
||||
return tk.Type == token.CommentType
|
||||
}
|
||||
|
||||
func (c *context) progressIgnoreComment(num int) {
|
||||
if c.parent != nil {
|
||||
c.parent.progressIgnoreComment(num)
|
||||
}
|
||||
if c.size <= c.idx+num {
|
||||
c.idx = c.size
|
||||
} else {
|
||||
c.idx += num
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) progress(num int) {
|
||||
if c.isCurrentCommentToken() {
|
||||
return
|
||||
}
|
||||
c.progressIgnoreComment(num)
|
||||
}
|
||||
|
||||
func newContext(tokens token.Tokens, mode Mode) *context {
|
||||
filteredTokens := []*token.Token{}
|
||||
if mode&ParseComments != 0 {
|
||||
filteredTokens = tokens
|
||||
} else {
|
||||
for _, tk := range tokens {
|
||||
if tk.Type == token.CommentType {
|
||||
continue
|
||||
}
|
||||
// keep prev/next reference between tokens containing comments
|
||||
// https://github.com/goccy/go-yaml/issues/254
|
||||
filteredTokens = append(filteredTokens, tk)
|
||||
}
|
||||
}
|
||||
return &context{
|
||||
idx: 0,
|
||||
size: len(filteredTokens),
|
||||
tokens: token.Tokens(filteredTokens),
|
||||
mode: mode,
|
||||
path: "$",
|
||||
}
|
||||
}
|
||||
714
vendor/github.com/goccy/go-yaml/parser/parser.go
generated
vendored
Normal file
714
vendor/github.com/goccy/go-yaml/parser/parser.go
generated
vendored
Normal file
@@ -0,0 +1,714 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/internal/errors"
|
||||
"github.com/goccy/go-yaml/lexer"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type parser struct{}
|
||||
|
||||
func (p *parser) parseMapping(ctx *context) (*ast.MappingNode, error) {
|
||||
mapTk := ctx.currentToken()
|
||||
node := ast.Mapping(mapTk, true)
|
||||
node.SetPath(ctx.path)
|
||||
ctx.progress(1) // skip MappingStart token
|
||||
for ctx.next() {
|
||||
tk := ctx.currentToken()
|
||||
if tk.Type == token.MappingEndType {
|
||||
node.End = tk
|
||||
return node, nil
|
||||
} else if tk.Type == token.CollectEntryType {
|
||||
ctx.progress(1)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err := p.parseMappingValue(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse mapping value in mapping node")
|
||||
}
|
||||
mvnode, ok := value.(*ast.MappingValueNode)
|
||||
if !ok {
|
||||
return nil, errors.ErrSyntax("failed to parse flow mapping node", value.GetToken())
|
||||
}
|
||||
node.Values = append(node.Values, mvnode)
|
||||
ctx.progress(1)
|
||||
}
|
||||
return nil, errors.ErrSyntax("unterminated flow mapping", node.GetToken())
|
||||
}
|
||||
|
||||
func (p *parser) parseSequence(ctx *context) (*ast.SequenceNode, error) {
|
||||
node := ast.Sequence(ctx.currentToken(), true)
|
||||
node.SetPath(ctx.path)
|
||||
ctx.progress(1) // skip SequenceStart token
|
||||
for ctx.next() {
|
||||
tk := ctx.currentToken()
|
||||
if tk.Type == token.SequenceEndType {
|
||||
node.End = tk
|
||||
break
|
||||
} else if tk.Type == token.CollectEntryType {
|
||||
ctx.progress(1)
|
||||
continue
|
||||
}
|
||||
|
||||
value, err := p.parseToken(ctx.withIndex(uint(len(node.Values))), tk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse sequence value in flow sequence node")
|
||||
}
|
||||
node.Values = append(node.Values, value)
|
||||
ctx.progress(1)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseTag(ctx *context) (*ast.TagNode, error) {
|
||||
tagToken := ctx.currentToken()
|
||||
node := ast.Tag(tagToken)
|
||||
node.SetPath(ctx.path)
|
||||
ctx.progress(1) // skip tag token
|
||||
var (
|
||||
value ast.Node
|
||||
err error
|
||||
)
|
||||
switch token.ReservedTagKeyword(tagToken.Value) {
|
||||
case token.MappingTag,
|
||||
token.OrderedMapTag:
|
||||
value, err = p.parseMapping(ctx)
|
||||
case token.IntegerTag,
|
||||
token.FloatTag,
|
||||
token.StringTag,
|
||||
token.BinaryTag,
|
||||
token.TimestampTag,
|
||||
token.NullTag:
|
||||
typ := ctx.currentToken().Type
|
||||
if typ == token.LiteralType || typ == token.FoldedType {
|
||||
value, err = p.parseLiteral(ctx)
|
||||
} else {
|
||||
value = p.parseScalarValue(ctx.currentToken())
|
||||
}
|
||||
case token.SequenceTag,
|
||||
token.SetTag:
|
||||
err = errors.ErrSyntax(fmt.Sprintf("sorry, currently not supported %s tag", tagToken.Value), tagToken)
|
||||
default:
|
||||
// custom tag
|
||||
value, err = p.parseToken(ctx, ctx.currentToken())
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse tag value")
|
||||
}
|
||||
node.Value = value
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) removeLeftSideNewLineCharacter(src string) string {
|
||||
// CR or LF or CRLF
|
||||
return strings.TrimLeft(strings.TrimLeft(strings.TrimLeft(src, "\r"), "\n"), "\r\n")
|
||||
}
|
||||
|
||||
func (p *parser) existsNewLineCharacter(src string) bool {
|
||||
if strings.Index(src, "\n") > 0 {
|
||||
return true
|
||||
}
|
||||
if strings.Index(src, "\r") > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *parser) validateMapKey(tk *token.Token) error {
|
||||
if tk.Type != token.StringType {
|
||||
return nil
|
||||
}
|
||||
origin := p.removeLeftSideNewLineCharacter(tk.Origin)
|
||||
if p.existsNewLineCharacter(origin) {
|
||||
return errors.ErrSyntax("unexpected key name", tk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) createNullToken(base *token.Token) *token.Token {
|
||||
pos := *(base.Position)
|
||||
pos.Column++
|
||||
return token.New("null", "null", &pos)
|
||||
}
|
||||
|
||||
func (p *parser) parseMapValue(ctx *context, key ast.MapKeyNode, colonToken *token.Token) (ast.Node, error) {
|
||||
node, err := p.createMapValueNode(ctx, key, colonToken)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create map value node")
|
||||
}
|
||||
if node != nil && node.GetPath() == "" {
|
||||
node.SetPath(ctx.path)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) createMapValueNode(ctx *context, key ast.MapKeyNode, colonToken *token.Token) (ast.Node, error) {
|
||||
tk := ctx.currentToken()
|
||||
if tk == nil {
|
||||
nullToken := p.createNullToken(colonToken)
|
||||
ctx.insertToken(ctx.idx, nullToken)
|
||||
return ast.Null(nullToken), nil
|
||||
}
|
||||
|
||||
if tk.Position.Column == key.GetToken().Position.Column && tk.Type == token.StringType {
|
||||
// in this case,
|
||||
// ----
|
||||
// key: <value does not defined>
|
||||
// next
|
||||
nullToken := p.createNullToken(colonToken)
|
||||
ctx.insertToken(ctx.idx, nullToken)
|
||||
return ast.Null(nullToken), nil
|
||||
}
|
||||
|
||||
if tk.Position.Column < key.GetToken().Position.Column {
|
||||
// in this case,
|
||||
// ----
|
||||
// key: <value does not defined>
|
||||
// next
|
||||
nullToken := p.createNullToken(colonToken)
|
||||
ctx.insertToken(ctx.idx, nullToken)
|
||||
return ast.Null(nullToken), nil
|
||||
}
|
||||
|
||||
value, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse mapping 'value' node")
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (p *parser) validateMapValue(ctx *context, key, value ast.Node) error {
|
||||
keyColumn := key.GetToken().Position.Column
|
||||
valueColumn := value.GetToken().Position.Column
|
||||
if keyColumn != valueColumn {
|
||||
return nil
|
||||
}
|
||||
if value.Type() != ast.StringType {
|
||||
return nil
|
||||
}
|
||||
ntk := ctx.nextToken()
|
||||
if ntk == nil || (ntk.Type != token.MappingValueType && ntk.Type != token.SequenceEntryType) {
|
||||
return errors.ErrSyntax("could not found expected ':' token", value.GetToken())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) {
|
||||
key, err := p.parseMapKey(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse map key")
|
||||
}
|
||||
keyText := key.GetToken().Value
|
||||
key.SetPath(ctx.withChild(keyText).path)
|
||||
if err := p.validateMapKey(key.GetToken()); err != nil {
|
||||
return nil, errors.Wrapf(err, "validate mapping key error")
|
||||
}
|
||||
ctx.progress(1) // progress to mapping value token
|
||||
tk := ctx.currentToken() // get mapping value token
|
||||
if tk == nil {
|
||||
return nil, errors.ErrSyntax("unexpected map", key.GetToken())
|
||||
}
|
||||
ctx.progress(1) // progress to value token
|
||||
if err := p.setSameLineCommentIfExists(ctx.withChild(keyText), key); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to set same line comment to node")
|
||||
}
|
||||
if key.GetComment() != nil {
|
||||
// if current token is comment, GetComment() is not nil.
|
||||
// then progress to value token
|
||||
ctx.progressIgnoreComment(1)
|
||||
}
|
||||
|
||||
value, err := p.parseMapValue(ctx.withChild(keyText), key, tk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse map value")
|
||||
}
|
||||
if err := p.validateMapValue(ctx, key, value); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to validate map value")
|
||||
}
|
||||
|
||||
mvnode := ast.MappingValue(tk, key, value)
|
||||
mvnode.SetPath(ctx.withChild(keyText).path)
|
||||
node := ast.Mapping(tk, false, mvnode)
|
||||
node.SetPath(ctx.withChild(keyText).path)
|
||||
|
||||
ntk := ctx.nextNotCommentToken()
|
||||
antk := ctx.afterNextNotCommentToken()
|
||||
for antk != nil && antk.Type == token.MappingValueType &&
|
||||
ntk.Position.Column == key.GetToken().Position.Column {
|
||||
ctx.progressIgnoreComment(1)
|
||||
value, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse mapping node")
|
||||
}
|
||||
switch value.Type() {
|
||||
case ast.MappingType:
|
||||
c := value.(*ast.MappingNode)
|
||||
comment := c.GetComment()
|
||||
for idx, v := range c.Values {
|
||||
if idx == 0 && comment != nil {
|
||||
if err := v.SetComment(comment); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to set comment token to node")
|
||||
}
|
||||
}
|
||||
node.Values = append(node.Values, v)
|
||||
}
|
||||
case ast.MappingValueType:
|
||||
node.Values = append(node.Values, value.(*ast.MappingValueNode))
|
||||
default:
|
||||
return nil, xerrors.Errorf("failed to parse mapping value node node is %s", value.Type())
|
||||
}
|
||||
ntk = ctx.nextNotCommentToken()
|
||||
antk = ctx.afterNextNotCommentToken()
|
||||
}
|
||||
if len(node.Values) == 1 {
|
||||
mapKeyCol := mvnode.Key.GetToken().Position.Column
|
||||
commentTk := ctx.nextToken()
|
||||
if commentTk != nil && commentTk.Type == token.CommentType && mapKeyCol <= commentTk.Position.Column {
|
||||
// If the comment is in the same or deeper column as the last element column in map value,
|
||||
// treat it as a footer comment for the last element.
|
||||
comment := p.parseFootComment(ctx, mapKeyCol)
|
||||
mvnode.FootComment = comment
|
||||
}
|
||||
return mvnode, nil
|
||||
}
|
||||
mapCol := node.GetToken().Position.Column
|
||||
commentTk := ctx.nextToken()
|
||||
if commentTk != nil && commentTk.Type == token.CommentType && mapCol <= commentTk.Position.Column {
|
||||
// If the comment is in the same or deeper column as the last element column in map value,
|
||||
// treat it as a footer comment for the last element.
|
||||
comment := p.parseFootComment(ctx, mapCol)
|
||||
node.FootComment = comment
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseSequenceEntry(ctx *context) (*ast.SequenceNode, error) {
|
||||
tk := ctx.currentToken()
|
||||
sequenceNode := ast.Sequence(tk, false)
|
||||
sequenceNode.SetPath(ctx.path)
|
||||
curColumn := tk.Position.Column
|
||||
for tk.Type == token.SequenceEntryType {
|
||||
ctx.progress(1) // skip sequence token
|
||||
tk = ctx.currentToken()
|
||||
if tk == nil {
|
||||
return nil, errors.ErrSyntax("empty sequence entry", ctx.previousToken())
|
||||
}
|
||||
var comment *ast.CommentGroupNode
|
||||
if tk.Type == token.CommentType {
|
||||
comment = p.parseCommentOnly(ctx)
|
||||
tk = ctx.currentToken()
|
||||
if tk.Type != token.SequenceEntryType {
|
||||
break
|
||||
}
|
||||
ctx.progress(1) // skip sequence token
|
||||
}
|
||||
value, err := p.parseToken(ctx.withIndex(uint(len(sequenceNode.Values))), ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse sequence")
|
||||
}
|
||||
if comment != nil {
|
||||
comment.SetPath(ctx.withIndex(uint(len(sequenceNode.Values))).path)
|
||||
sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, comment)
|
||||
} else {
|
||||
sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, nil)
|
||||
}
|
||||
sequenceNode.Values = append(sequenceNode.Values, value)
|
||||
tk = ctx.nextNotCommentToken()
|
||||
if tk == nil {
|
||||
break
|
||||
}
|
||||
if tk.Type != token.SequenceEntryType {
|
||||
break
|
||||
}
|
||||
if tk.Position.Column != curColumn {
|
||||
break
|
||||
}
|
||||
ctx.progressIgnoreComment(1)
|
||||
}
|
||||
commentTk := ctx.nextToken()
|
||||
if commentTk != nil && commentTk.Type == token.CommentType && curColumn <= commentTk.Position.Column {
|
||||
// If the comment is in the same or deeper column as the last element column in sequence value,
|
||||
// treat it as a footer comment for the last element.
|
||||
comment := p.parseFootComment(ctx, curColumn)
|
||||
sequenceNode.FootComment = comment
|
||||
}
|
||||
return sequenceNode, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseAnchor(ctx *context) (*ast.AnchorNode, error) {
|
||||
tk := ctx.currentToken()
|
||||
anchor := ast.Anchor(tk)
|
||||
anchor.SetPath(ctx.path)
|
||||
ntk := ctx.nextToken()
|
||||
if ntk == nil {
|
||||
return nil, errors.ErrSyntax("unexpected anchor. anchor name is undefined", tk)
|
||||
}
|
||||
ctx.progress(1) // skip anchor token
|
||||
name, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parser anchor name node")
|
||||
}
|
||||
anchor.Name = name
|
||||
ntk = ctx.nextToken()
|
||||
if ntk == nil {
|
||||
return nil, errors.ErrSyntax("unexpected anchor. anchor value is undefined", ctx.currentToken())
|
||||
}
|
||||
ctx.progress(1)
|
||||
value, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parser anchor name node")
|
||||
}
|
||||
anchor.Value = value
|
||||
return anchor, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseAlias(ctx *context) (*ast.AliasNode, error) {
|
||||
tk := ctx.currentToken()
|
||||
alias := ast.Alias(tk)
|
||||
alias.SetPath(ctx.path)
|
||||
ntk := ctx.nextToken()
|
||||
if ntk == nil {
|
||||
return nil, errors.ErrSyntax("unexpected alias. alias name is undefined", tk)
|
||||
}
|
||||
ctx.progress(1) // skip alias token
|
||||
name, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parser alias name node")
|
||||
}
|
||||
alias.Value = name
|
||||
return alias, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseMapKey(ctx *context) (ast.MapKeyNode, error) {
|
||||
tk := ctx.currentToken()
|
||||
if value := p.parseScalarValue(tk); value != nil {
|
||||
return value, nil
|
||||
}
|
||||
switch tk.Type {
|
||||
case token.MergeKeyType:
|
||||
return ast.MergeKey(tk), nil
|
||||
case token.MappingKeyType:
|
||||
return p.parseMappingKey(ctx)
|
||||
}
|
||||
return nil, errors.ErrSyntax("unexpected mapping key", tk)
|
||||
}
|
||||
|
||||
func (p *parser) parseStringValue(tk *token.Token) *ast.StringNode {
|
||||
switch tk.Type {
|
||||
case token.StringType,
|
||||
token.SingleQuoteType,
|
||||
token.DoubleQuoteType:
|
||||
return ast.String(tk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) parseScalarValueWithComment(ctx *context, tk *token.Token) (ast.ScalarNode, error) {
|
||||
node := p.parseScalarValue(tk)
|
||||
if node == nil {
|
||||
return nil, nil
|
||||
}
|
||||
node.SetPath(ctx.path)
|
||||
if p.isSameLineComment(ctx.nextToken(), node) {
|
||||
ctx.progress(1)
|
||||
if err := p.setSameLineCommentIfExists(ctx, node); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to set same line comment to node")
|
||||
}
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseScalarValue(tk *token.Token) ast.ScalarNode {
|
||||
if node := p.parseStringValue(tk); node != nil {
|
||||
return node
|
||||
}
|
||||
switch tk.Type {
|
||||
case token.NullType:
|
||||
return ast.Null(tk)
|
||||
case token.BoolType:
|
||||
return ast.Bool(tk)
|
||||
case token.IntegerType,
|
||||
token.BinaryIntegerType,
|
||||
token.OctetIntegerType,
|
||||
token.HexIntegerType:
|
||||
return ast.Integer(tk)
|
||||
case token.FloatType:
|
||||
return ast.Float(tk)
|
||||
case token.InfinityType:
|
||||
return ast.Infinity(tk)
|
||||
case token.NanType:
|
||||
return ast.Nan(tk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) parseDirective(ctx *context) (*ast.DirectiveNode, error) {
|
||||
node := ast.Directive(ctx.currentToken())
|
||||
ctx.progress(1) // skip directive token
|
||||
value, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse directive value")
|
||||
}
|
||||
node.Value = value
|
||||
ctx.progress(1)
|
||||
tk := ctx.currentToken()
|
||||
if tk == nil {
|
||||
// Since current token is nil, use the previous token to specify
|
||||
// the syntax error location.
|
||||
return nil, errors.ErrSyntax("unexpected directive value. document not started", ctx.previousToken())
|
||||
}
|
||||
if tk.Type != token.DocumentHeaderType {
|
||||
return nil, errors.ErrSyntax("unexpected directive value. document not started", ctx.currentToken())
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseLiteral(ctx *context) (*ast.LiteralNode, error) {
|
||||
node := ast.Literal(ctx.currentToken())
|
||||
ctx.progress(1) // skip literal/folded token
|
||||
|
||||
tk := ctx.currentToken()
|
||||
var comment *ast.CommentGroupNode
|
||||
if tk.Type == token.CommentType {
|
||||
comment = p.parseCommentOnly(ctx)
|
||||
comment.SetPath(ctx.path)
|
||||
if err := node.SetComment(comment); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to set comment to literal")
|
||||
}
|
||||
tk = ctx.currentToken()
|
||||
}
|
||||
value, err := p.parseToken(ctx, tk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse literal/folded value")
|
||||
}
|
||||
snode, ok := value.(*ast.StringNode)
|
||||
if !ok {
|
||||
return nil, errors.ErrSyntax("unexpected token. required string token", value.GetToken())
|
||||
}
|
||||
node.Value = snode
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) isSameLineComment(tk *token.Token, node ast.Node) bool {
|
||||
if tk == nil {
|
||||
return false
|
||||
}
|
||||
if tk.Type != token.CommentType {
|
||||
return false
|
||||
}
|
||||
return tk.Position.Line == node.GetToken().Position.Line
|
||||
}
|
||||
|
||||
func (p *parser) setSameLineCommentIfExists(ctx *context, node ast.Node) error {
|
||||
tk := ctx.currentToken()
|
||||
if !p.isSameLineComment(tk, node) {
|
||||
return nil
|
||||
}
|
||||
comment := ast.CommentGroup([]*token.Token{tk})
|
||||
comment.SetPath(ctx.path)
|
||||
if err := node.SetComment(comment); err != nil {
|
||||
return errors.Wrapf(err, "failed to set comment token to ast.Node")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) parseDocument(ctx *context) (*ast.DocumentNode, error) {
|
||||
startTk := ctx.currentToken()
|
||||
ctx.progress(1) // skip document header token
|
||||
body, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse document body")
|
||||
}
|
||||
node := ast.Document(startTk, body)
|
||||
if ntk := ctx.nextToken(); ntk != nil && ntk.Type == token.DocumentEndType {
|
||||
node.End = ntk
|
||||
ctx.progress(1)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseCommentOnly(ctx *context) *ast.CommentGroupNode {
|
||||
commentTokens := []*token.Token{}
|
||||
for {
|
||||
tk := ctx.currentToken()
|
||||
if tk == nil {
|
||||
break
|
||||
}
|
||||
if tk.Type != token.CommentType {
|
||||
break
|
||||
}
|
||||
commentTokens = append(commentTokens, tk)
|
||||
ctx.progressIgnoreComment(1) // skip comment token
|
||||
}
|
||||
return ast.CommentGroup(commentTokens)
|
||||
}
|
||||
|
||||
func (p *parser) parseFootComment(ctx *context, col int) *ast.CommentGroupNode {
|
||||
commentTokens := []*token.Token{}
|
||||
for {
|
||||
ctx.progressIgnoreComment(1)
|
||||
commentTokens = append(commentTokens, ctx.currentToken())
|
||||
|
||||
nextTk := ctx.nextToken()
|
||||
if nextTk == nil {
|
||||
break
|
||||
}
|
||||
if nextTk.Type != token.CommentType {
|
||||
break
|
||||
}
|
||||
if col > nextTk.Position.Column {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ast.CommentGroup(commentTokens)
|
||||
}
|
||||
|
||||
func (p *parser) parseComment(ctx *context) (ast.Node, error) {
|
||||
group := p.parseCommentOnly(ctx)
|
||||
node, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse node after comment")
|
||||
}
|
||||
if node == nil {
|
||||
return group, nil
|
||||
}
|
||||
group.SetPath(node.GetPath())
|
||||
if err := node.SetComment(group); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to set comment token to node")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseMappingKey(ctx *context) (*ast.MappingKeyNode, error) {
|
||||
keyTk := ctx.currentToken()
|
||||
node := ast.MappingKey(keyTk)
|
||||
node.SetPath(ctx.path)
|
||||
ctx.progress(1) // skip mapping key token
|
||||
value, err := p.parseToken(ctx.withChild(keyTk.Value), ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse map key")
|
||||
}
|
||||
node.Value = value
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseToken(ctx *context, tk *token.Token) (ast.Node, error) {
|
||||
node, err := p.createNodeFromToken(ctx, tk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create node from token")
|
||||
}
|
||||
if node != nil && node.GetPath() == "" {
|
||||
node.SetPath(ctx.path)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *parser) createNodeFromToken(ctx *context, tk *token.Token) (ast.Node, error) {
|
||||
if tk == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if tk.NextType() == token.MappingValueType {
|
||||
node, err := p.parseMappingValue(ctx)
|
||||
return node, err
|
||||
}
|
||||
node, err := p.parseScalarValueWithComment(ctx, tk)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse scalar value")
|
||||
}
|
||||
if node != nil {
|
||||
return node, nil
|
||||
}
|
||||
switch tk.Type {
|
||||
case token.CommentType:
|
||||
return p.parseComment(ctx)
|
||||
case token.MappingKeyType:
|
||||
return p.parseMappingKey(ctx)
|
||||
case token.DocumentHeaderType:
|
||||
return p.parseDocument(ctx)
|
||||
case token.MappingStartType:
|
||||
return p.parseMapping(ctx)
|
||||
case token.SequenceStartType:
|
||||
return p.parseSequence(ctx)
|
||||
case token.SequenceEntryType:
|
||||
return p.parseSequenceEntry(ctx)
|
||||
case token.AnchorType:
|
||||
return p.parseAnchor(ctx)
|
||||
case token.AliasType:
|
||||
return p.parseAlias(ctx)
|
||||
case token.DirectiveType:
|
||||
return p.parseDirective(ctx)
|
||||
case token.TagType:
|
||||
return p.parseTag(ctx)
|
||||
case token.LiteralType, token.FoldedType:
|
||||
return p.parseLiteral(ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *parser) parse(tokens token.Tokens, mode Mode) (*ast.File, error) {
|
||||
ctx := newContext(tokens, mode)
|
||||
file := &ast.File{Docs: []*ast.DocumentNode{}}
|
||||
for ctx.next() {
|
||||
node, err := p.parseToken(ctx, ctx.currentToken())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
ctx.progressIgnoreComment(1)
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
if doc, ok := node.(*ast.DocumentNode); ok {
|
||||
file.Docs = append(file.Docs, doc)
|
||||
} else {
|
||||
file.Docs = append(file.Docs, ast.Document(nil, node))
|
||||
}
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
type Mode uint
|
||||
|
||||
const (
|
||||
ParseComments Mode = 1 << iota // parse comments and add them to AST
|
||||
)
|
||||
|
||||
// ParseBytes parse from byte slice, and returns ast.File
|
||||
func ParseBytes(bytes []byte, mode Mode) (*ast.File, error) {
|
||||
tokens := lexer.Tokenize(string(bytes))
|
||||
f, err := Parse(tokens, mode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Parse parse from token instances, and returns ast.File
|
||||
func Parse(tokens token.Tokens, mode Mode) (*ast.File, error) {
|
||||
var p parser
|
||||
f, err := p.parse(tokens, mode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Parse parse from filename, and returns ast.File
|
||||
func ParseFile(filename string, mode Mode) (*ast.File, error) {
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read file: %s", filename)
|
||||
}
|
||||
f, err := ParseBytes(file, mode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
f.Name = filename
|
||||
return f, nil
|
||||
}
|
||||
794
vendor/github.com/goccy/go-yaml/path.go
generated
vendored
Normal file
794
vendor/github.com/goccy/go-yaml/path.go
generated
vendored
Normal file
@@ -0,0 +1,794 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/internal/errors"
|
||||
"github.com/goccy/go-yaml/parser"
|
||||
"github.com/goccy/go-yaml/printer"
|
||||
)
|
||||
|
||||
// PathString create Path from string
|
||||
//
|
||||
// YAMLPath rule
|
||||
// $ : the root object/element
|
||||
// . : child operator
|
||||
// .. : recursive descent
|
||||
// [num] : object/element of array by number
|
||||
// [*] : all objects/elements for array.
|
||||
//
|
||||
// If you want to use reserved characters such as `.` and `*` as a key name,
|
||||
// enclose them in single quotation as follows ( $.foo.'bar.baz-*'.hoge ).
|
||||
// If you want to use a single quote with reserved characters, escape it with `\` ( $.foo.'bar.baz\'s value'.hoge ).
|
||||
func PathString(s string) (*Path, error) {
|
||||
buf := []rune(s)
|
||||
length := len(buf)
|
||||
cursor := 0
|
||||
builder := &PathBuilder{}
|
||||
for cursor < length {
|
||||
c := buf[cursor]
|
||||
switch c {
|
||||
case '$':
|
||||
builder = builder.Root()
|
||||
cursor++
|
||||
case '.':
|
||||
b, buf, c, err := parsePathDot(builder, buf, cursor)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse path of dot")
|
||||
}
|
||||
length = len(buf)
|
||||
builder = b
|
||||
cursor = c
|
||||
case '[':
|
||||
b, buf, c, err := parsePathIndex(builder, buf, cursor)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse path of index")
|
||||
}
|
||||
length = len(buf)
|
||||
builder = b
|
||||
cursor = c
|
||||
default:
|
||||
return nil, errors.Wrapf(ErrInvalidPathString, "invalid path at %d", cursor)
|
||||
}
|
||||
}
|
||||
return builder.Build(), nil
|
||||
}
|
||||
|
||||
func parsePathRecursive(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, int, error) {
|
||||
length := len(buf)
|
||||
cursor += 2 // skip .. characters
|
||||
start := cursor
|
||||
for ; cursor < length; cursor++ {
|
||||
c := buf[cursor]
|
||||
switch c {
|
||||
case '$':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '..' character")
|
||||
case '*':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '..' character")
|
||||
case '.', '[':
|
||||
goto end
|
||||
case ']':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '..' character")
|
||||
}
|
||||
}
|
||||
end:
|
||||
if start == cursor {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "not found recursive selector")
|
||||
}
|
||||
return b.Recursive(string(buf[start:cursor])), buf, cursor, nil
|
||||
}
|
||||
|
||||
func parsePathDot(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, int, error) {
|
||||
length := len(buf)
|
||||
if cursor+1 < length && buf[cursor+1] == '.' {
|
||||
b, buf, c, err := parsePathRecursive(b, buf, cursor)
|
||||
if err != nil {
|
||||
return nil, nil, 0, errors.Wrapf(err, "failed to parse path of recursive")
|
||||
}
|
||||
return b, buf, c, nil
|
||||
}
|
||||
cursor++ // skip . character
|
||||
start := cursor
|
||||
|
||||
// if started single quote, looking for end single quote char
|
||||
if cursor < length && buf[cursor] == '\'' {
|
||||
return parseQuotedKey(b, buf, cursor)
|
||||
}
|
||||
for ; cursor < length; cursor++ {
|
||||
c := buf[cursor]
|
||||
switch c {
|
||||
case '$':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '.' character")
|
||||
case '*':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '.' character")
|
||||
case '.', '[':
|
||||
goto end
|
||||
case ']':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '.' character")
|
||||
}
|
||||
}
|
||||
end:
|
||||
if start == cursor {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "cloud not find by empty key")
|
||||
}
|
||||
return b.child(string(buf[start:cursor])), buf, cursor, nil
|
||||
}
|
||||
|
||||
func parseQuotedKey(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, int, error) {
|
||||
cursor++ // skip single quote
|
||||
start := cursor
|
||||
length := len(buf)
|
||||
var foundEndDelim bool
|
||||
for ; cursor < length; cursor++ {
|
||||
switch buf[cursor] {
|
||||
case '\\':
|
||||
buf = append(append([]rune{}, buf[:cursor]...), buf[cursor+1:]...)
|
||||
length = len(buf)
|
||||
case '\'':
|
||||
foundEndDelim = true
|
||||
goto end
|
||||
}
|
||||
}
|
||||
end:
|
||||
if !foundEndDelim {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "could not find end delimiter for key")
|
||||
}
|
||||
if start == cursor {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "could not find by empty key")
|
||||
}
|
||||
selector := buf[start:cursor]
|
||||
cursor++
|
||||
if cursor < length {
|
||||
switch buf[cursor] {
|
||||
case '$':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '.' character")
|
||||
case '*':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '.' character")
|
||||
case ']':
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '.' character")
|
||||
}
|
||||
}
|
||||
return b.child(string(selector)), buf, cursor, nil
|
||||
}
|
||||
|
||||
func parsePathIndex(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, int, error) {
|
||||
length := len(buf)
|
||||
cursor++ // skip '[' character
|
||||
if length <= cursor {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "unexpected end of YAML Path")
|
||||
}
|
||||
c := buf[cursor]
|
||||
switch c {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*':
|
||||
start := cursor
|
||||
cursor++
|
||||
for ; cursor < length; cursor++ {
|
||||
c := buf[cursor]
|
||||
switch c {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
if buf[cursor] != ']' {
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", string(buf[cursor]), cursor)
|
||||
}
|
||||
numOrAll := string(buf[start:cursor])
|
||||
if numOrAll == "*" {
|
||||
return b.IndexAll(), buf, cursor + 1, nil
|
||||
}
|
||||
num, err := strconv.ParseInt(numOrAll, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, 0, errors.Wrapf(err, "failed to parse number")
|
||||
}
|
||||
return b.Index(uint(num)), buf, cursor + 1, nil
|
||||
}
|
||||
return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", c, cursor)
|
||||
}
|
||||
|
||||
// Path represent YAMLPath ( like a JSONPath ).
|
||||
type Path struct {
|
||||
node pathNode
|
||||
}
|
||||
|
||||
// String path to text.
|
||||
func (p *Path) String() string {
|
||||
return p.node.String()
|
||||
}
|
||||
|
||||
// Read decode from r and set extracted value by YAMLPath to v.
|
||||
func (p *Path) Read(r io.Reader, v interface{}) error {
|
||||
node, err := p.ReadNode(r)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read node")
|
||||
}
|
||||
if err := Unmarshal([]byte(node.String()), v); err != nil {
|
||||
return errors.Wrapf(err, "failed to unmarshal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadNode create AST from r and extract node by YAMLPath.
|
||||
func (p *Path) ReadNode(r io.Reader) (ast.Node, error) {
|
||||
if p.node == nil {
|
||||
return nil, ErrInvalidPath
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if _, err := io.Copy(&buf, r); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to copy from reader")
|
||||
}
|
||||
f, err := parser.ParseBytes(buf.Bytes(), 0)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse yaml")
|
||||
}
|
||||
node, err := p.FilterFile(f)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter from ast.File")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// Filter filter from target by YAMLPath and set it to v.
|
||||
func (p *Path) Filter(target, v interface{}) error {
|
||||
b, err := Marshal(target)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to marshal target value")
|
||||
}
|
||||
if err := p.Read(bytes.NewBuffer(b), v); err != nil {
|
||||
return errors.Wrapf(err, "failed to read")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FilterFile filter from ast.File by YAMLPath.
|
||||
func (p *Path) FilterFile(f *ast.File) (ast.Node, error) {
|
||||
for _, doc := range f.Docs {
|
||||
node, err := p.FilterNode(doc.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node)
|
||||
}
|
||||
if node != nil {
|
||||
return node, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(ErrNotFoundNode, "failed to find path ( %s )", p.node)
|
||||
}
|
||||
|
||||
// FilterNode filter from node by YAMLPath.
|
||||
func (p *Path) FilterNode(node ast.Node) (ast.Node, error) {
|
||||
n, err := p.node.filter(node)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// MergeFromReader merge YAML text into ast.File.
|
||||
func (p *Path) MergeFromReader(dst *ast.File, src io.Reader) error {
|
||||
var buf bytes.Buffer
|
||||
if _, err := io.Copy(&buf, src); err != nil {
|
||||
return errors.Wrapf(err, "failed to copy from reader")
|
||||
}
|
||||
file, err := parser.ParseBytes(buf.Bytes(), 0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
if err := p.MergeFromFile(dst, file); err != nil {
|
||||
return errors.Wrapf(err, "failed to merge file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MergeFromFile merge ast.File into ast.File.
|
||||
func (p *Path) MergeFromFile(dst *ast.File, src *ast.File) error {
|
||||
base, err := p.FilterFile(dst)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to filter file")
|
||||
}
|
||||
for _, doc := range src.Docs {
|
||||
if err := ast.Merge(base, doc); err != nil {
|
||||
return errors.Wrapf(err, "failed to merge")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MergeFromNode merge ast.Node into ast.File.
|
||||
func (p *Path) MergeFromNode(dst *ast.File, src ast.Node) error {
|
||||
base, err := p.FilterFile(dst)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to filter file")
|
||||
}
|
||||
if err := ast.Merge(base, src); err != nil {
|
||||
return errors.Wrapf(err, "failed to merge")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReplaceWithReader replace ast.File with io.Reader.
|
||||
func (p *Path) ReplaceWithReader(dst *ast.File, src io.Reader) error {
|
||||
var buf bytes.Buffer
|
||||
if _, err := io.Copy(&buf, src); err != nil {
|
||||
return errors.Wrapf(err, "failed to copy from reader")
|
||||
}
|
||||
file, err := parser.ParseBytes(buf.Bytes(), 0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse")
|
||||
}
|
||||
if err := p.ReplaceWithFile(dst, file); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReplaceWithFile replace ast.File with ast.File.
|
||||
func (p *Path) ReplaceWithFile(dst *ast.File, src *ast.File) error {
|
||||
for _, doc := range src.Docs {
|
||||
if err := p.ReplaceWithNode(dst, doc); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace file by path ( %s )", p.node)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReplaceNode replace ast.File with ast.Node.
|
||||
func (p *Path) ReplaceWithNode(dst *ast.File, node ast.Node) error {
|
||||
for _, doc := range dst.Docs {
|
||||
if node.Type() == ast.DocumentType {
|
||||
node = node.(*ast.DocumentNode).Body
|
||||
}
|
||||
if err := p.node.replace(doc.Body, node); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace node by path ( %s )", p.node)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AnnotateSource add annotation to passed source ( see section 5.1 in README.md ).
|
||||
func (p *Path) AnnotateSource(source []byte, colored bool) ([]byte, error) {
|
||||
file, err := parser.ParseBytes([]byte(source), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := p.FilterFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pp printer.Printer
|
||||
return []byte(pp.PrintErrorToken(node.GetToken(), colored)), nil
|
||||
}
|
||||
|
||||
// PathBuilder represent builder for YAMLPath.
|
||||
type PathBuilder struct {
|
||||
root *rootNode
|
||||
node pathNode
|
||||
}
|
||||
|
||||
// Root add '$' to current path.
|
||||
func (b *PathBuilder) Root() *PathBuilder {
|
||||
root := newRootNode()
|
||||
return &PathBuilder{root: root, node: root}
|
||||
}
|
||||
|
||||
// IndexAll add '[*]' to current path.
|
||||
func (b *PathBuilder) IndexAll() *PathBuilder {
|
||||
b.node = b.node.chain(newIndexAllNode())
|
||||
return b
|
||||
}
|
||||
|
||||
// Recursive add '..selector' to current path.
|
||||
func (b *PathBuilder) Recursive(selector string) *PathBuilder {
|
||||
b.node = b.node.chain(newRecursiveNode(selector))
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *PathBuilder) containsReservedPathCharacters(path string) bool {
|
||||
if strings.Contains(path, ".") {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(path, "*") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *PathBuilder) enclosedSingleQuote(name string) bool {
|
||||
return strings.HasPrefix(name, "'") && strings.HasSuffix(name, "'")
|
||||
}
|
||||
|
||||
func (b *PathBuilder) normalizeSelectorName(name string) string {
|
||||
if b.enclosedSingleQuote(name) {
|
||||
// already escaped name
|
||||
return name
|
||||
}
|
||||
if b.containsReservedPathCharacters(name) {
|
||||
escapedName := strings.ReplaceAll(name, `'`, `\'`)
|
||||
return "'" + escapedName + "'"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (b *PathBuilder) child(name string) *PathBuilder {
|
||||
b.node = b.node.chain(newSelectorNode(name))
|
||||
return b
|
||||
}
|
||||
|
||||
// Child add '.name' to current path.
|
||||
func (b *PathBuilder) Child(name string) *PathBuilder {
|
||||
return b.child(b.normalizeSelectorName(name))
|
||||
}
|
||||
|
||||
// Index add '[idx]' to current path.
|
||||
func (b *PathBuilder) Index(idx uint) *PathBuilder {
|
||||
b.node = b.node.chain(newIndexNode(idx))
|
||||
return b
|
||||
}
|
||||
|
||||
// Build build YAMLPath.
|
||||
func (b *PathBuilder) Build() *Path {
|
||||
return &Path{node: b.root}
|
||||
}
|
||||
|
||||
type pathNode interface {
|
||||
fmt.Stringer
|
||||
chain(pathNode) pathNode
|
||||
filter(ast.Node) (ast.Node, error)
|
||||
replace(ast.Node, ast.Node) error
|
||||
}
|
||||
|
||||
type basePathNode struct {
|
||||
child pathNode
|
||||
}
|
||||
|
||||
func (n *basePathNode) chain(node pathNode) pathNode {
|
||||
n.child = node
|
||||
return node
|
||||
}
|
||||
|
||||
type rootNode struct {
|
||||
*basePathNode
|
||||
}
|
||||
|
||||
func newRootNode() *rootNode {
|
||||
return &rootNode{basePathNode: &basePathNode{}}
|
||||
}
|
||||
|
||||
func (n *rootNode) String() string {
|
||||
s := "$"
|
||||
if n.child != nil {
|
||||
s += n.child.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *rootNode) filter(node ast.Node) (ast.Node, error) {
|
||||
if n.child == nil {
|
||||
return nil, nil
|
||||
}
|
||||
filtered, err := n.child.filter(node)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func (n *rootNode) replace(node ast.Node, target ast.Node) error {
|
||||
if n.child == nil {
|
||||
return nil
|
||||
}
|
||||
if err := n.child.replace(node, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type selectorNode struct {
|
||||
*basePathNode
|
||||
selector string
|
||||
}
|
||||
|
||||
func newSelectorNode(selector string) *selectorNode {
|
||||
return &selectorNode{
|
||||
basePathNode: &basePathNode{},
|
||||
selector: selector,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *selectorNode) filter(node ast.Node) (ast.Node, error) {
|
||||
switch node.Type() {
|
||||
case ast.MappingType:
|
||||
for _, value := range node.(*ast.MappingNode).Values {
|
||||
key := value.Key.GetToken().Value
|
||||
if key == n.selector {
|
||||
if n.child == nil {
|
||||
return value.Value, nil
|
||||
}
|
||||
filtered, err := n.child.filter(value.Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
}
|
||||
case ast.MappingValueType:
|
||||
value := node.(*ast.MappingValueNode)
|
||||
key := value.Key.GetToken().Value
|
||||
if key == n.selector {
|
||||
if n.child == nil {
|
||||
return value.Value, nil
|
||||
}
|
||||
filtered, err := n.child.filter(value.Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
default:
|
||||
return nil, errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type())
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (n *selectorNode) replaceMapValue(value *ast.MappingValueNode, target ast.Node) error {
|
||||
key := value.Key.GetToken().Value
|
||||
if key != n.selector {
|
||||
return nil
|
||||
}
|
||||
if n.child == nil {
|
||||
if err := value.Replace(target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
} else {
|
||||
if err := n.child.replace(value.Value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *selectorNode) replace(node ast.Node, target ast.Node) error {
|
||||
switch node.Type() {
|
||||
case ast.MappingType:
|
||||
for _, value := range node.(*ast.MappingNode).Values {
|
||||
if err := n.replaceMapValue(value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace map value")
|
||||
}
|
||||
}
|
||||
case ast.MappingValueType:
|
||||
value := node.(*ast.MappingValueNode)
|
||||
if err := n.replaceMapValue(value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace map value")
|
||||
}
|
||||
default:
|
||||
return errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *selectorNode) String() string {
|
||||
s := fmt.Sprintf(".%s", n.selector)
|
||||
if n.child != nil {
|
||||
s += n.child.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type indexNode struct {
|
||||
*basePathNode
|
||||
selector uint
|
||||
}
|
||||
|
||||
func newIndexNode(selector uint) *indexNode {
|
||||
return &indexNode{
|
||||
basePathNode: &basePathNode{},
|
||||
selector: selector,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *indexNode) filter(node ast.Node) (ast.Node, error) {
|
||||
if node.Type() != ast.SequenceType {
|
||||
return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
|
||||
}
|
||||
sequence := node.(*ast.SequenceNode)
|
||||
if n.selector >= uint(len(sequence.Values)) {
|
||||
return nil, errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values)
|
||||
}
|
||||
value := sequence.Values[n.selector]
|
||||
if n.child == nil {
|
||||
return value, nil
|
||||
}
|
||||
filtered, err := n.child.filter(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func (n *indexNode) replace(node ast.Node, target ast.Node) error {
|
||||
if node.Type() != ast.SequenceType {
|
||||
return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
|
||||
}
|
||||
sequence := node.(*ast.SequenceNode)
|
||||
if n.selector >= uint(len(sequence.Values)) {
|
||||
return errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values)
|
||||
}
|
||||
if n.child == nil {
|
||||
if err := sequence.Replace(int(n.selector), target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := n.child.replace(sequence.Values[n.selector], target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *indexNode) String() string {
|
||||
s := fmt.Sprintf("[%d]", n.selector)
|
||||
if n.child != nil {
|
||||
s += n.child.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type indexAllNode struct {
|
||||
*basePathNode
|
||||
}
|
||||
|
||||
func newIndexAllNode() *indexAllNode {
|
||||
return &indexAllNode{
|
||||
basePathNode: &basePathNode{},
|
||||
}
|
||||
}
|
||||
|
||||
func (n *indexAllNode) String() string {
|
||||
s := "[*]"
|
||||
if n.child != nil {
|
||||
s += n.child.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *indexAllNode) filter(node ast.Node) (ast.Node, error) {
|
||||
if node.Type() != ast.SequenceType {
|
||||
return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
|
||||
}
|
||||
sequence := node.(*ast.SequenceNode)
|
||||
if n.child == nil {
|
||||
return sequence, nil
|
||||
}
|
||||
out := *sequence
|
||||
out.Values = []ast.Node{}
|
||||
for _, value := range sequence.Values {
|
||||
filtered, err := n.child.filter(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
out.Values = append(out.Values, filtered)
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (n *indexAllNode) replace(node ast.Node, target ast.Node) error {
|
||||
if node.Type() != ast.SequenceType {
|
||||
return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
|
||||
}
|
||||
sequence := node.(*ast.SequenceNode)
|
||||
if n.child == nil {
|
||||
for idx := range sequence.Values {
|
||||
if err := sequence.Replace(idx, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for _, value := range sequence.Values {
|
||||
if err := n.child.replace(value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type recursiveNode struct {
|
||||
*basePathNode
|
||||
selector string
|
||||
}
|
||||
|
||||
func newRecursiveNode(selector string) *recursiveNode {
|
||||
return &recursiveNode{
|
||||
basePathNode: &basePathNode{},
|
||||
selector: selector,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *recursiveNode) String() string {
|
||||
s := fmt.Sprintf("..%s", n.selector)
|
||||
if n.child != nil {
|
||||
s += n.child.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (n *recursiveNode) filterNode(node ast.Node) (*ast.SequenceNode, error) {
|
||||
sequence := &ast.SequenceNode{BaseNode: &ast.BaseNode{}}
|
||||
switch typedNode := node.(type) {
|
||||
case *ast.MappingNode:
|
||||
for _, value := range typedNode.Values {
|
||||
seq, err := n.filterNode(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
sequence.Values = append(sequence.Values, seq.Values...)
|
||||
}
|
||||
case *ast.MappingValueNode:
|
||||
key := typedNode.Key.GetToken().Value
|
||||
if n.selector == key {
|
||||
sequence.Values = append(sequence.Values, typedNode.Value)
|
||||
}
|
||||
seq, err := n.filterNode(typedNode.Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
sequence.Values = append(sequence.Values, seq.Values...)
|
||||
case *ast.SequenceNode:
|
||||
for _, value := range typedNode.Values {
|
||||
seq, err := n.filterNode(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
sequence.Values = append(sequence.Values, seq.Values...)
|
||||
}
|
||||
}
|
||||
return sequence, nil
|
||||
}
|
||||
|
||||
func (n *recursiveNode) filter(node ast.Node) (ast.Node, error) {
|
||||
sequence, err := n.filterNode(node)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to filter")
|
||||
}
|
||||
sequence.Start = node.GetToken()
|
||||
return sequence, nil
|
||||
}
|
||||
|
||||
func (n *recursiveNode) replaceNode(node ast.Node, target ast.Node) error {
|
||||
switch typedNode := node.(type) {
|
||||
case *ast.MappingNode:
|
||||
for _, value := range typedNode.Values {
|
||||
if err := n.replaceNode(value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
case *ast.MappingValueNode:
|
||||
key := typedNode.Key.GetToken().Value
|
||||
if n.selector == key {
|
||||
if err := typedNode.Replace(target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
if err := n.replaceNode(typedNode.Value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
case *ast.SequenceNode:
|
||||
for _, value := range typedNode.Values {
|
||||
if err := n.replaceNode(value, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *recursiveNode) replace(node ast.Node, target ast.Node) error {
|
||||
if err := n.replaceNode(node, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to replace")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
352
vendor/github.com/goccy/go-yaml/printer/printer.go
generated
vendored
Normal file
352
vendor/github.com/goccy/go-yaml/printer/printer.go
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
// Property additional property set for each the token
|
||||
type Property struct {
|
||||
Prefix string
|
||||
Suffix string
|
||||
}
|
||||
|
||||
// PrintFunc returns property instance
|
||||
type PrintFunc func() *Property
|
||||
|
||||
// Printer create text from token collection or ast
|
||||
type Printer struct {
|
||||
LineNumber bool
|
||||
LineNumberFormat func(num int) string
|
||||
MapKey PrintFunc
|
||||
Anchor PrintFunc
|
||||
Alias PrintFunc
|
||||
Bool PrintFunc
|
||||
String PrintFunc
|
||||
Number PrintFunc
|
||||
}
|
||||
|
||||
func defaultLineNumberFormat(num int) string {
|
||||
return fmt.Sprintf("%2d | ", num)
|
||||
}
|
||||
|
||||
func (p *Printer) property(tk *token.Token) *Property {
|
||||
prop := &Property{}
|
||||
switch tk.PreviousType() {
|
||||
case token.AnchorType:
|
||||
if p.Anchor != nil {
|
||||
return p.Anchor()
|
||||
}
|
||||
return prop
|
||||
case token.AliasType:
|
||||
if p.Alias != nil {
|
||||
return p.Alias()
|
||||
}
|
||||
return prop
|
||||
}
|
||||
switch tk.NextType() {
|
||||
case token.MappingValueType:
|
||||
if p.MapKey != nil {
|
||||
return p.MapKey()
|
||||
}
|
||||
return prop
|
||||
}
|
||||
switch tk.Type {
|
||||
case token.BoolType:
|
||||
if p.Bool != nil {
|
||||
return p.Bool()
|
||||
}
|
||||
return prop
|
||||
case token.AnchorType:
|
||||
if p.Anchor != nil {
|
||||
return p.Anchor()
|
||||
}
|
||||
return prop
|
||||
case token.AliasType:
|
||||
if p.Anchor != nil {
|
||||
return p.Alias()
|
||||
}
|
||||
return prop
|
||||
case token.StringType, token.SingleQuoteType, token.DoubleQuoteType:
|
||||
if p.String != nil {
|
||||
return p.String()
|
||||
}
|
||||
return prop
|
||||
case token.IntegerType, token.FloatType:
|
||||
if p.Number != nil {
|
||||
return p.Number()
|
||||
}
|
||||
return prop
|
||||
default:
|
||||
}
|
||||
return prop
|
||||
}
|
||||
|
||||
// PrintTokens create text from token collection
|
||||
func (p *Printer) PrintTokens(tokens token.Tokens) string {
|
||||
if len(tokens) == 0 {
|
||||
return ""
|
||||
}
|
||||
if p.LineNumber {
|
||||
if p.LineNumberFormat == nil {
|
||||
p.LineNumberFormat = defaultLineNumberFormat
|
||||
}
|
||||
}
|
||||
texts := []string{}
|
||||
lineNumber := tokens[0].Position.Line
|
||||
for _, tk := range tokens {
|
||||
lines := strings.Split(tk.Origin, "\n")
|
||||
prop := p.property(tk)
|
||||
header := ""
|
||||
if p.LineNumber {
|
||||
header = p.LineNumberFormat(lineNumber)
|
||||
}
|
||||
if len(lines) == 1 {
|
||||
line := prop.Prefix + lines[0] + prop.Suffix
|
||||
if len(texts) == 0 {
|
||||
texts = append(texts, header+line)
|
||||
lineNumber++
|
||||
} else {
|
||||
text := texts[len(texts)-1]
|
||||
texts[len(texts)-1] = text + line
|
||||
}
|
||||
} else {
|
||||
for idx, src := range lines {
|
||||
if p.LineNumber {
|
||||
header = p.LineNumberFormat(lineNumber)
|
||||
}
|
||||
line := prop.Prefix + src + prop.Suffix
|
||||
if idx == 0 {
|
||||
if len(texts) == 0 {
|
||||
texts = append(texts, header+line)
|
||||
lineNumber++
|
||||
} else {
|
||||
text := texts[len(texts)-1]
|
||||
texts[len(texts)-1] = text + line
|
||||
}
|
||||
} else {
|
||||
texts = append(texts, fmt.Sprintf("%s%s", header, line))
|
||||
lineNumber++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(texts, "\n")
|
||||
}
|
||||
|
||||
// PrintNode create text from ast.Node
|
||||
func (p *Printer) PrintNode(node ast.Node) []byte {
|
||||
return []byte(fmt.Sprintf("%+v\n", node))
|
||||
}
|
||||
|
||||
const escape = "\x1b"
|
||||
|
||||
func format(attr color.Attribute) string {
|
||||
return fmt.Sprintf("%s[%dm", escape, attr)
|
||||
}
|
||||
|
||||
func (p *Printer) setDefaultColorSet() {
|
||||
p.Bool = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiMagenta),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
p.Number = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiMagenta),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
p.MapKey = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiCyan),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
p.Anchor = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiYellow),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
p.Alias = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiYellow),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
p.String = func() *Property {
|
||||
return &Property{
|
||||
Prefix: format(color.FgHiGreen),
|
||||
Suffix: format(color.Reset),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Printer) PrintErrorMessage(msg string, isColored bool) string {
|
||||
if isColored {
|
||||
return fmt.Sprintf("%s%s%s",
|
||||
format(color.FgHiRed),
|
||||
msg,
|
||||
format(color.Reset),
|
||||
)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func (p *Printer) removeLeftSideNewLineChar(src string) string {
|
||||
return strings.TrimLeft(strings.TrimLeft(strings.TrimLeft(src, "\r"), "\n"), "\r\n")
|
||||
}
|
||||
|
||||
func (p *Printer) removeRightSideNewLineChar(src string) string {
|
||||
return strings.TrimRight(strings.TrimRight(strings.TrimRight(src, "\r"), "\n"), "\r\n")
|
||||
}
|
||||
|
||||
func (p *Printer) removeRightSideWhiteSpaceChar(src string) string {
|
||||
return p.removeRightSideNewLineChar(strings.TrimRight(src, " "))
|
||||
}
|
||||
|
||||
func (p *Printer) newLineCount(s string) int {
|
||||
src := []rune(s)
|
||||
size := len(src)
|
||||
cnt := 0
|
||||
for i := 0; i < size; i++ {
|
||||
c := src[i]
|
||||
switch c {
|
||||
case '\r':
|
||||
if i+1 < size && src[i+1] == '\n' {
|
||||
i++
|
||||
}
|
||||
cnt++
|
||||
case '\n':
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func (p *Printer) isNewLineLastChar(s string) bool {
|
||||
for i := len(s) - 1; i > 0; i-- {
|
||||
c := s[i]
|
||||
switch c {
|
||||
case ' ':
|
||||
continue
|
||||
case '\n', '\r':
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Printer) printBeforeTokens(tk *token.Token, minLine, extLine int) token.Tokens {
|
||||
for {
|
||||
if tk.Prev == nil {
|
||||
break
|
||||
}
|
||||
if tk.Prev.Position.Line < minLine {
|
||||
break
|
||||
}
|
||||
tk = tk.Prev
|
||||
}
|
||||
minTk := tk.Clone()
|
||||
if minTk.Prev != nil {
|
||||
// add white spaces to minTk by prev token
|
||||
prev := minTk.Prev
|
||||
whiteSpaceLen := len(prev.Origin) - len(strings.TrimRight(prev.Origin, " "))
|
||||
minTk.Origin = strings.Repeat(" ", whiteSpaceLen) + minTk.Origin
|
||||
}
|
||||
minTk.Origin = p.removeLeftSideNewLineChar(minTk.Origin)
|
||||
tokens := token.Tokens{minTk}
|
||||
tk = minTk.Next
|
||||
for tk != nil && tk.Position.Line <= extLine {
|
||||
clonedTk := tk.Clone()
|
||||
tokens.Add(clonedTk)
|
||||
tk = clonedTk.Next
|
||||
}
|
||||
lastTk := tokens[len(tokens)-1]
|
||||
trimmedOrigin := p.removeRightSideWhiteSpaceChar(lastTk.Origin)
|
||||
suffix := lastTk.Origin[len(trimmedOrigin):]
|
||||
lastTk.Origin = trimmedOrigin
|
||||
|
||||
if lastTk.Next != nil && len(suffix) > 1 {
|
||||
next := lastTk.Next.Clone()
|
||||
// add suffix to header of next token
|
||||
if suffix[0] == '\n' || suffix[0] == '\r' {
|
||||
suffix = suffix[1:]
|
||||
}
|
||||
next.Origin = suffix + next.Origin
|
||||
lastTk.Next = next
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func (p *Printer) printAfterTokens(tk *token.Token, maxLine int) token.Tokens {
|
||||
tokens := token.Tokens{}
|
||||
if tk == nil {
|
||||
return tokens
|
||||
}
|
||||
if tk.Position.Line > maxLine {
|
||||
return tokens
|
||||
}
|
||||
minTk := tk.Clone()
|
||||
minTk.Origin = p.removeLeftSideNewLineChar(minTk.Origin)
|
||||
tokens.Add(minTk)
|
||||
tk = minTk.Next
|
||||
for tk != nil && tk.Position.Line <= maxLine {
|
||||
clonedTk := tk.Clone()
|
||||
tokens.Add(clonedTk)
|
||||
tk = clonedTk.Next
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func (p *Printer) setupErrorTokenFormat(annotateLine int, isColored bool) {
|
||||
prefix := func(annotateLine, num int) string {
|
||||
if annotateLine == num {
|
||||
return fmt.Sprintf("> %2d | ", num)
|
||||
}
|
||||
return fmt.Sprintf(" %2d | ", num)
|
||||
}
|
||||
p.LineNumber = true
|
||||
p.LineNumberFormat = func(num int) string {
|
||||
if isColored {
|
||||
fn := color.New(color.Bold, color.FgHiWhite).SprintFunc()
|
||||
return fn(prefix(annotateLine, num))
|
||||
}
|
||||
return prefix(annotateLine, num)
|
||||
}
|
||||
if isColored {
|
||||
p.setDefaultColorSet()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Printer) PrintErrorToken(tk *token.Token, isColored bool) string {
|
||||
errToken := tk
|
||||
curLine := tk.Position.Line
|
||||
curExtLine := curLine + p.newLineCount(p.removeLeftSideNewLineChar(tk.Origin))
|
||||
if p.isNewLineLastChar(tk.Origin) {
|
||||
// if last character ( exclude white space ) is new line character, ignore it.
|
||||
curExtLine--
|
||||
}
|
||||
|
||||
minLine := int(math.Max(float64(curLine-3), 1))
|
||||
maxLine := curExtLine + 3
|
||||
p.setupErrorTokenFormat(curLine, isColored)
|
||||
|
||||
beforeTokens := p.printBeforeTokens(tk, minLine, curExtLine)
|
||||
lastTk := beforeTokens[len(beforeTokens)-1]
|
||||
afterTokens := p.printAfterTokens(lastTk.Next, maxLine)
|
||||
|
||||
beforeSource := p.PrintTokens(beforeTokens)
|
||||
prefixSpaceNum := len(fmt.Sprintf(" %2d | ", curLine))
|
||||
annotateLine := strings.Repeat(" ", prefixSpaceNum+errToken.Position.Column-1) + "^"
|
||||
afterSource := p.PrintTokens(afterTokens)
|
||||
return fmt.Sprintf("%s\n%s\n%s", beforeSource, annotateLine, afterSource)
|
||||
}
|
||||
229
vendor/github.com/goccy/go-yaml/scanner/context.go
generated
vendored
Normal file
229
vendor/github.com/goccy/go-yaml/scanner/context.go
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/goccy/go-yaml/token"
|
||||
)
|
||||
|
||||
const whitespace = ' '
|
||||
|
||||
// Context context at scanning
|
||||
type Context struct {
|
||||
idx int
|
||||
size int
|
||||
notSpaceCharPos int
|
||||
notSpaceOrgCharPos int
|
||||
src []rune
|
||||
buf []rune
|
||||
obuf []rune
|
||||
tokens token.Tokens
|
||||
isRawFolded bool
|
||||
isLiteral bool
|
||||
isFolded bool
|
||||
isSingleLine bool
|
||||
literalOpt string
|
||||
}
|
||||
|
||||
var (
|
||||
ctxPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return createContext()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func createContext() *Context {
|
||||
return &Context{
|
||||
idx: 0,
|
||||
tokens: token.Tokens{},
|
||||
isSingleLine: true,
|
||||
}
|
||||
}
|
||||
|
||||
func newContext(src []rune) *Context {
|
||||
ctx := ctxPool.Get().(*Context)
|
||||
ctx.reset(src)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (c *Context) release() {
|
||||
ctxPool.Put(c)
|
||||
}
|
||||
|
||||
func (c *Context) reset(src []rune) {
|
||||
c.idx = 0
|
||||
c.size = len(src)
|
||||
c.src = src
|
||||
c.tokens = c.tokens[:0]
|
||||
c.resetBuffer()
|
||||
c.isRawFolded = false
|
||||
c.isSingleLine = true
|
||||
c.isLiteral = false
|
||||
c.isFolded = false
|
||||
c.literalOpt = ""
|
||||
}
|
||||
|
||||
func (c *Context) resetBuffer() {
|
||||
c.buf = c.buf[:0]
|
||||
c.obuf = c.obuf[:0]
|
||||
c.notSpaceCharPos = 0
|
||||
c.notSpaceOrgCharPos = 0
|
||||
}
|
||||
|
||||
func (c *Context) isSaveIndentMode() bool {
|
||||
return c.isLiteral || c.isFolded || c.isRawFolded
|
||||
}
|
||||
|
||||
func (c *Context) breakLiteral() {
|
||||
c.isLiteral = false
|
||||
c.isRawFolded = false
|
||||
c.isFolded = false
|
||||
c.literalOpt = ""
|
||||
}
|
||||
|
||||
func (c *Context) addToken(tk *token.Token) {
|
||||
if tk == nil {
|
||||
return
|
||||
}
|
||||
c.tokens = append(c.tokens, tk)
|
||||
}
|
||||
|
||||
func (c *Context) addBuf(r rune) {
|
||||
if len(c.buf) == 0 && r == ' ' {
|
||||
return
|
||||
}
|
||||
c.buf = append(c.buf, r)
|
||||
if r != ' ' && r != '\t' {
|
||||
c.notSpaceCharPos = len(c.buf)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) addOriginBuf(r rune) {
|
||||
c.obuf = append(c.obuf, r)
|
||||
if r != ' ' && r != '\t' {
|
||||
c.notSpaceOrgCharPos = len(c.obuf)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) removeRightSpaceFromBuf() int {
|
||||
trimmedBuf := c.obuf[:c.notSpaceOrgCharPos]
|
||||
buflen := len(trimmedBuf)
|
||||
diff := len(c.obuf) - buflen
|
||||
if diff > 0 {
|
||||
c.obuf = c.obuf[:buflen]
|
||||
c.buf = c.bufferedSrc()
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
func (c *Context) isDocument() bool {
|
||||
return c.isLiteral || c.isFolded || c.isRawFolded
|
||||
}
|
||||
|
||||
func (c *Context) isEOS() bool {
|
||||
return len(c.src)-1 <= c.idx
|
||||
}
|
||||
|
||||
func (c *Context) isNextEOS() bool {
|
||||
return len(c.src)-1 <= c.idx+1
|
||||
}
|
||||
|
||||
func (c *Context) next() bool {
|
||||
return c.idx < c.size
|
||||
}
|
||||
|
||||
func (c *Context) source(s, e int) string {
|
||||
return string(c.src[s:e])
|
||||
}
|
||||
|
||||
func (c *Context) previousChar() rune {
|
||||
if c.idx > 0 {
|
||||
return c.src[c.idx-1]
|
||||
}
|
||||
return rune(0)
|
||||
}
|
||||
|
||||
func (c *Context) currentChar() rune {
|
||||
if c.size > c.idx {
|
||||
return c.src[c.idx]
|
||||
}
|
||||
return rune(0)
|
||||
}
|
||||
|
||||
func (c *Context) currentCharWithSkipWhitespace() rune {
|
||||
idx := c.idx
|
||||
for c.size > idx {
|
||||
ch := c.src[idx]
|
||||
if ch != whitespace {
|
||||
return ch
|
||||
}
|
||||
idx++
|
||||
}
|
||||
return rune(0)
|
||||
}
|
||||
|
||||
func (c *Context) nextChar() rune {
|
||||
if c.size > c.idx+1 {
|
||||
return c.src[c.idx+1]
|
||||
}
|
||||
return rune(0)
|
||||
}
|
||||
|
||||
func (c *Context) repeatNum(r rune) int {
|
||||
cnt := 0
|
||||
for i := c.idx; i < c.size; i++ {
|
||||
if c.src[i] == r {
|
||||
cnt++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func (c *Context) progress(num int) {
|
||||
c.idx += num
|
||||
}
|
||||
|
||||
func (c *Context) nextPos() int {
|
||||
return c.idx + 1
|
||||
}
|
||||
|
||||
func (c *Context) existsBuffer() bool {
|
||||
return len(c.bufferedSrc()) != 0
|
||||
}
|
||||
|
||||
func (c *Context) bufferedSrc() []rune {
|
||||
src := c.buf[:c.notSpaceCharPos]
|
||||
if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" {
|
||||
// remove end '\n' character
|
||||
src = src[:len(src)-1]
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
func (c *Context) bufferedToken(pos *token.Position) *token.Token {
|
||||
if c.idx == 0 {
|
||||
return nil
|
||||
}
|
||||
source := c.bufferedSrc()
|
||||
if len(source) == 0 {
|
||||
return nil
|
||||
}
|
||||
var tk *token.Token
|
||||
if c.isDocument() {
|
||||
tk = token.String(string(source), string(c.obuf), pos)
|
||||
} else {
|
||||
tk = token.New(string(source), string(c.obuf), pos)
|
||||
}
|
||||
c.resetBuffer()
|
||||
return tk
|
||||
}
|
||||
|
||||
func (c *Context) lastToken() *token.Token {
|
||||
if len(c.tokens) != 0 {
|
||||
return c.tokens[len(c.tokens)-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
903
vendor/github.com/goccy/go-yaml/scanner/scanner.go
generated
vendored
Normal file
903
vendor/github.com/goccy/go-yaml/scanner/scanner.go
generated
vendored
Normal file
@@ -0,0 +1,903 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-yaml/token"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// IndentState state for indent
|
||||
type IndentState int
|
||||
|
||||
const (
|
||||
// IndentStateEqual equals previous indent
|
||||
IndentStateEqual IndentState = iota
|
||||
// IndentStateUp more indent than previous
|
||||
IndentStateUp
|
||||
// IndentStateDown less indent than previous
|
||||
IndentStateDown
|
||||
// IndentStateKeep uses not indent token
|
||||
IndentStateKeep
|
||||
)
|
||||
|
||||
// Scanner holds the scanner's internal state while processing a given text.
|
||||
// It can be allocated as part of another data structure but must be initialized via Init before use.
|
||||
type Scanner struct {
|
||||
source []rune
|
||||
sourcePos int
|
||||
sourceSize int
|
||||
line int
|
||||
column int
|
||||
offset int
|
||||
prevIndentLevel int
|
||||
prevIndentNum int
|
||||
prevIndentColumn int
|
||||
docStartColumn int
|
||||
indentLevel int
|
||||
indentNum int
|
||||
isFirstCharAtLine bool
|
||||
isAnchor bool
|
||||
startedFlowSequenceNum int
|
||||
startedFlowMapNum int
|
||||
indentState IndentState
|
||||
savedPos *token.Position
|
||||
}
|
||||
|
||||
func (s *Scanner) pos() *token.Position {
|
||||
return &token.Position{
|
||||
Line: s.line,
|
||||
Column: s.column,
|
||||
Offset: s.offset,
|
||||
IndentNum: s.indentNum,
|
||||
IndentLevel: s.indentLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scanner) bufferedToken(ctx *Context) *token.Token {
|
||||
if s.savedPos != nil {
|
||||
tk := ctx.bufferedToken(s.savedPos)
|
||||
s.savedPos = nil
|
||||
return tk
|
||||
}
|
||||
line := s.line
|
||||
column := s.column - len(ctx.buf)
|
||||
level := s.indentLevel
|
||||
if ctx.isSaveIndentMode() {
|
||||
line -= s.newLineCount(ctx.buf)
|
||||
column = strings.Index(string(ctx.obuf), string(ctx.buf)) + 1
|
||||
// Since we are in a literal, folded or raw folded
|
||||
// we can use the indent level from the last token.
|
||||
last := ctx.lastToken()
|
||||
if last != nil { // The last token should never be nil here.
|
||||
level = last.Position.IndentLevel + 1
|
||||
}
|
||||
}
|
||||
return ctx.bufferedToken(&token.Position{
|
||||
Line: line,
|
||||
Column: column,
|
||||
Offset: s.offset - len(ctx.buf),
|
||||
IndentNum: s.indentNum,
|
||||
IndentLevel: level,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Scanner) progressColumn(ctx *Context, num int) {
|
||||
s.column += num
|
||||
s.offset += num
|
||||
ctx.progress(num)
|
||||
}
|
||||
|
||||
func (s *Scanner) progressLine(ctx *Context) {
|
||||
s.column = 1
|
||||
s.line++
|
||||
s.offset++
|
||||
s.indentNum = 0
|
||||
s.isFirstCharAtLine = true
|
||||
s.isAnchor = false
|
||||
ctx.progress(1)
|
||||
}
|
||||
|
||||
func (s *Scanner) isNeededKeepPreviousIndentNum(ctx *Context, c rune) bool {
|
||||
if !s.isChangedToIndentStateUp() {
|
||||
return false
|
||||
}
|
||||
if ctx.isDocument() {
|
||||
return true
|
||||
}
|
||||
if c == '-' && ctx.existsBuffer() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Scanner) isNewLineChar(c rune) bool {
|
||||
if c == '\n' {
|
||||
return true
|
||||
}
|
||||
if c == '\r' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Scanner) newLineCount(src []rune) int {
|
||||
size := len(src)
|
||||
cnt := 0
|
||||
for i := 0; i < size; i++ {
|
||||
c := src[i]
|
||||
switch c {
|
||||
case '\r':
|
||||
if i+1 < size && src[i+1] == '\n' {
|
||||
i++
|
||||
}
|
||||
cnt++
|
||||
case '\n':
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func (s *Scanner) updateIndentState(ctx *Context) {
|
||||
indentNumBasedIndentState := s.indentState
|
||||
if s.prevIndentNum < s.indentNum {
|
||||
s.indentLevel = s.prevIndentLevel + 1
|
||||
indentNumBasedIndentState = IndentStateUp
|
||||
} else if s.prevIndentNum == s.indentNum {
|
||||
s.indentLevel = s.prevIndentLevel
|
||||
indentNumBasedIndentState = IndentStateEqual
|
||||
} else {
|
||||
indentNumBasedIndentState = IndentStateDown
|
||||
if s.prevIndentLevel > 0 {
|
||||
s.indentLevel = s.prevIndentLevel - 1
|
||||
}
|
||||
}
|
||||
|
||||
if s.prevIndentColumn > 0 {
|
||||
if s.prevIndentColumn < s.column {
|
||||
s.indentState = IndentStateUp
|
||||
} else if s.prevIndentColumn != s.column || indentNumBasedIndentState != IndentStateEqual {
|
||||
// The following case ( current position is 'd' ), some variables becomes like here
|
||||
// - prevIndentColumn: 1 of 'a'
|
||||
// - indentNumBasedIndentState: IndentStateDown because d's indentNum(1) is less than c's indentNum(3).
|
||||
// Therefore, s.prevIndentColumn(1) == s.column(1) is true, but we want to treat this as IndentStateDown.
|
||||
// So, we look also current indentState value by the above prevIndentNum based logic, and determins finally indentState.
|
||||
// ---
|
||||
// a:
|
||||
// b
|
||||
// c
|
||||
// d: e
|
||||
// ^
|
||||
s.indentState = IndentStateDown
|
||||
} else {
|
||||
s.indentState = IndentStateEqual
|
||||
}
|
||||
} else {
|
||||
s.indentState = indentNumBasedIndentState
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scanner) updateIndent(ctx *Context, c rune) {
|
||||
if s.isFirstCharAtLine && s.isNewLineChar(c) && ctx.isDocument() {
|
||||
return
|
||||
}
|
||||
if s.isFirstCharAtLine && c == ' ' {
|
||||
s.indentNum++
|
||||
return
|
||||
}
|
||||
if !s.isFirstCharAtLine {
|
||||
s.indentState = IndentStateKeep
|
||||
return
|
||||
}
|
||||
s.updateIndentState(ctx)
|
||||
s.isFirstCharAtLine = false
|
||||
if s.isNeededKeepPreviousIndentNum(ctx, c) {
|
||||
return
|
||||
}
|
||||
if s.indentState != IndentStateUp {
|
||||
s.prevIndentColumn = 0
|
||||
}
|
||||
s.prevIndentNum = s.indentNum
|
||||
s.prevIndentLevel = s.indentLevel
|
||||
}
|
||||
|
||||
func (s *Scanner) isChangedToIndentStateDown() bool {
|
||||
return s.indentState == IndentStateDown
|
||||
}
|
||||
|
||||
func (s *Scanner) isChangedToIndentStateUp() bool {
|
||||
return s.indentState == IndentStateUp
|
||||
}
|
||||
|
||||
func (s *Scanner) isChangedToIndentStateEqual() bool {
|
||||
return s.indentState == IndentStateEqual
|
||||
}
|
||||
|
||||
func (s *Scanner) addBufferedTokenIfExists(ctx *Context) {
|
||||
ctx.addToken(s.bufferedToken(ctx))
|
||||
}
|
||||
|
||||
func (s *Scanner) breakLiteral(ctx *Context) {
|
||||
s.docStartColumn = 0
|
||||
ctx.breakLiteral()
|
||||
}
|
||||
|
||||
func (s *Scanner) scanSingleQuote(ctx *Context) (tk *token.Token, pos int) {
|
||||
ctx.addOriginBuf('\'')
|
||||
srcpos := s.pos()
|
||||
startIndex := ctx.idx + 1
|
||||
src := ctx.src
|
||||
size := len(src)
|
||||
value := []rune{}
|
||||
isFirstLineChar := false
|
||||
isNewLine := false
|
||||
for idx := startIndex; idx < size; idx++ {
|
||||
if !isNewLine {
|
||||
s.progressColumn(ctx, 1)
|
||||
} else {
|
||||
isNewLine = false
|
||||
}
|
||||
c := src[idx]
|
||||
pos = idx + 1
|
||||
ctx.addOriginBuf(c)
|
||||
if s.isNewLineChar(c) {
|
||||
value = append(value, ' ')
|
||||
isFirstLineChar = true
|
||||
isNewLine = true
|
||||
s.progressLine(ctx)
|
||||
continue
|
||||
} else if c == ' ' && isFirstLineChar {
|
||||
continue
|
||||
} else if c != '\'' {
|
||||
value = append(value, c)
|
||||
isFirstLineChar = false
|
||||
continue
|
||||
}
|
||||
if idx+1 < len(ctx.src) && ctx.src[idx+1] == '\'' {
|
||||
// '' handle as ' character
|
||||
value = append(value, c)
|
||||
ctx.addOriginBuf(c)
|
||||
idx++
|
||||
continue
|
||||
}
|
||||
s.progressColumn(ctx, 1)
|
||||
tk = token.SingleQuote(string(value), string(ctx.obuf), srcpos)
|
||||
pos = idx - startIndex + 1
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hexToInt(b rune) int {
|
||||
if b >= 'A' && b <= 'F' {
|
||||
return int(b) - 'A' + 10
|
||||
}
|
||||
if b >= 'a' && b <= 'f' {
|
||||
return int(b) - 'a' + 10
|
||||
}
|
||||
return int(b) - '0'
|
||||
}
|
||||
|
||||
func hexRunesToInt(b []rune) int {
|
||||
sum := 0
|
||||
for i := 0; i < len(b); i++ {
|
||||
sum += hexToInt(b[i]) << (uint(len(b)-i-1) * 4)
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) {
|
||||
ctx.addOriginBuf('"')
|
||||
srcpos := s.pos()
|
||||
startIndex := ctx.idx + 1
|
||||
src := ctx.src
|
||||
size := len(src)
|
||||
value := []rune{}
|
||||
isFirstLineChar := false
|
||||
isNewLine := false
|
||||
for idx := startIndex; idx < size; idx++ {
|
||||
if !isNewLine {
|
||||
s.progressColumn(ctx, 1)
|
||||
} else {
|
||||
isNewLine = false
|
||||
}
|
||||
c := src[idx]
|
||||
pos = idx + 1
|
||||
ctx.addOriginBuf(c)
|
||||
if s.isNewLineChar(c) {
|
||||
value = append(value, ' ')
|
||||
isFirstLineChar = true
|
||||
isNewLine = true
|
||||
s.progressLine(ctx)
|
||||
continue
|
||||
} else if c == ' ' && isFirstLineChar {
|
||||
continue
|
||||
} else if c == '\\' {
|
||||
isFirstLineChar = false
|
||||
if idx+1 < size {
|
||||
nextChar := src[idx+1]
|
||||
switch nextChar {
|
||||
case 'b':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\b')
|
||||
idx++
|
||||
continue
|
||||
case 'e':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\x1B')
|
||||
idx++
|
||||
continue
|
||||
case 'f':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\f')
|
||||
idx++
|
||||
continue
|
||||
case 'n':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\n')
|
||||
idx++
|
||||
continue
|
||||
case 'v':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, '\v')
|
||||
idx++
|
||||
continue
|
||||
case 'L': // LS (#x2028)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA8'}...)
|
||||
idx++
|
||||
continue
|
||||
case 'N': // NEL (#x85)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\x85'}...)
|
||||
idx++
|
||||
continue
|
||||
case 'P': // PS (#x2029)
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xE2', '\x80', '\xA9'}...)
|
||||
idx++
|
||||
continue
|
||||
case '_': // #xA0
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, []rune{'\xC2', '\xA0'}...)
|
||||
idx++
|
||||
continue
|
||||
case '"':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
value = append(value, nextChar)
|
||||
idx++
|
||||
continue
|
||||
case 'x':
|
||||
if idx+3 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\x")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+4])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 3
|
||||
continue
|
||||
case 'u':
|
||||
if idx+5 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\u")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+6])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 5
|
||||
continue
|
||||
case 'U':
|
||||
if idx+9 >= size {
|
||||
// TODO: need to return error
|
||||
//err = xerrors.New("invalid escape character \\U")
|
||||
return
|
||||
}
|
||||
codeNum := hexRunesToInt(src[idx+2 : idx+10])
|
||||
value = append(value, rune(codeNum))
|
||||
idx += 9
|
||||
continue
|
||||
case '\\':
|
||||
ctx.addOriginBuf(nextChar)
|
||||
idx++
|
||||
}
|
||||
}
|
||||
value = append(value, c)
|
||||
continue
|
||||
} else if c != '"' {
|
||||
value = append(value, c)
|
||||
isFirstLineChar = false
|
||||
continue
|
||||
}
|
||||
s.progressColumn(ctx, 1)
|
||||
tk = token.DoubleQuote(string(value), string(ctx.obuf), srcpos)
|
||||
pos = idx - startIndex + 1
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Scanner) scanQuote(ctx *Context, ch rune) (tk *token.Token, pos int) {
|
||||
if ch == '\'' {
|
||||
return s.scanSingleQuote(ctx)
|
||||
}
|
||||
return s.scanDoubleQuote(ctx)
|
||||
}
|
||||
|
||||
func (s *Scanner) isMergeKey(ctx *Context) bool {
|
||||
if ctx.repeatNum('<') != 2 {
|
||||
return false
|
||||
}
|
||||
src := ctx.src
|
||||
size := len(src)
|
||||
for idx := ctx.idx + 2; idx < size; idx++ {
|
||||
c := src[idx]
|
||||
if c == ' ' {
|
||||
continue
|
||||
}
|
||||
if c != ':' {
|
||||
return false
|
||||
}
|
||||
if idx+1 < size {
|
||||
nc := src[idx+1]
|
||||
if nc == ' ' || s.isNewLineChar(nc) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Scanner) scanTag(ctx *Context) (tk *token.Token, pos int) {
|
||||
ctx.addOriginBuf('!')
|
||||
ctx.progress(1) // skip '!' character
|
||||
for idx, c := range ctx.src[ctx.idx:] {
|
||||
pos = idx + 1
|
||||
ctx.addOriginBuf(c)
|
||||
switch c {
|
||||
case ' ', '\n', '\r':
|
||||
value := ctx.source(ctx.idx-1, ctx.idx+idx)
|
||||
tk = token.Tag(value, string(ctx.obuf), s.pos())
|
||||
pos = len([]rune(value))
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Scanner) scanComment(ctx *Context) (tk *token.Token, pos int) {
|
||||
ctx.addOriginBuf('#')
|
||||
ctx.progress(1) // skip '#' character
|
||||
for idx, c := range ctx.src[ctx.idx:] {
|
||||
pos = idx + 1
|
||||
ctx.addOriginBuf(c)
|
||||
switch c {
|
||||
case '\n', '\r':
|
||||
if ctx.previousChar() == '\\' {
|
||||
continue
|
||||
}
|
||||
value := ctx.source(ctx.idx, ctx.idx+idx)
|
||||
tk = token.Comment(value, string(ctx.obuf), s.pos())
|
||||
pos = len([]rune(value)) + 1
|
||||
return
|
||||
}
|
||||
}
|
||||
// document ends with comment.
|
||||
value := string(ctx.src[ctx.idx:])
|
||||
tk = token.Comment(value, string(ctx.obuf), s.pos())
|
||||
pos = len([]rune(value)) + 1
|
||||
return
|
||||
}
|
||||
|
||||
func trimCommentFromLiteralOpt(text string) (string, error) {
|
||||
idx := strings.Index(text, "#")
|
||||
if idx < 0 {
|
||||
return text, nil
|
||||
}
|
||||
if idx == 0 {
|
||||
return "", xerrors.New("invalid literal header")
|
||||
}
|
||||
return text[:idx-1], nil
|
||||
}
|
||||
|
||||
func (s *Scanner) scanLiteral(ctx *Context, c rune) {
|
||||
ctx.addOriginBuf(c)
|
||||
if ctx.isEOS() {
|
||||
if ctx.isLiteral {
|
||||
ctx.addBuf(c)
|
||||
}
|
||||
value := ctx.bufferedSrc()
|
||||
ctx.addToken(token.String(string(value), string(ctx.obuf), s.pos()))
|
||||
ctx.resetBuffer()
|
||||
s.progressColumn(ctx, 1)
|
||||
} else if s.isNewLineChar(c) {
|
||||
if ctx.isLiteral {
|
||||
ctx.addBuf(c)
|
||||
} else {
|
||||
ctx.addBuf(' ')
|
||||
}
|
||||
s.progressLine(ctx)
|
||||
} else if s.isFirstCharAtLine && c == ' ' {
|
||||
if 0 < s.docStartColumn && s.docStartColumn <= s.column {
|
||||
ctx.addBuf(c)
|
||||
}
|
||||
s.progressColumn(ctx, 1)
|
||||
} else {
|
||||
if s.docStartColumn == 0 {
|
||||
s.docStartColumn = s.column
|
||||
}
|
||||
ctx.addBuf(c)
|
||||
s.progressColumn(ctx, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scanner) scanLiteralHeader(ctx *Context) (pos int, err error) {
|
||||
header := ctx.currentChar()
|
||||
ctx.addOriginBuf(header)
|
||||
ctx.progress(1) // skip '|' or '>' character
|
||||
for idx, c := range ctx.src[ctx.idx:] {
|
||||
pos = idx
|
||||
ctx.addOriginBuf(c)
|
||||
switch c {
|
||||
case '\n', '\r':
|
||||
value := ctx.source(ctx.idx, ctx.idx+idx)
|
||||
opt := strings.TrimRight(value, " ")
|
||||
orgOptLen := len(opt)
|
||||
opt, err = trimCommentFromLiteralOpt(opt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch opt {
|
||||
case "", "+", "-",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9":
|
||||
hasComment := len(opt) < orgOptLen
|
||||
if header == '|' {
|
||||
if hasComment {
|
||||
commentLen := orgOptLen - len(opt)
|
||||
headerPos := strings.Index(string(ctx.obuf), "|")
|
||||
litBuf := ctx.obuf[:len(ctx.obuf)-commentLen-headerPos]
|
||||
commentBuf := ctx.obuf[len(litBuf):]
|
||||
ctx.addToken(token.Literal("|"+opt, string(litBuf), s.pos()))
|
||||
s.column += len(litBuf)
|
||||
s.offset += len(litBuf)
|
||||
commentHeader := strings.Index(value, "#")
|
||||
ctx.addToken(token.Comment(string(value[commentHeader+1:]), string(commentBuf), s.pos()))
|
||||
} else {
|
||||
ctx.addToken(token.Literal("|"+opt, string(ctx.obuf), s.pos()))
|
||||
}
|
||||
ctx.isLiteral = true
|
||||
} else if header == '>' {
|
||||
if hasComment {
|
||||
commentLen := orgOptLen - len(opt)
|
||||
headerPos := strings.Index(string(ctx.obuf), ">")
|
||||
foldedBuf := ctx.obuf[:len(ctx.obuf)-commentLen-headerPos]
|
||||
commentBuf := ctx.obuf[len(foldedBuf):]
|
||||
ctx.addToken(token.Folded(">"+opt, string(foldedBuf), s.pos()))
|
||||
s.column += len(foldedBuf)
|
||||
s.offset += len(foldedBuf)
|
||||
commentHeader := strings.Index(value, "#")
|
||||
ctx.addToken(token.Comment(string(value[commentHeader+1:]), string(commentBuf), s.pos()))
|
||||
} else {
|
||||
ctx.addToken(token.Folded(">"+opt, string(ctx.obuf), s.pos()))
|
||||
}
|
||||
ctx.isFolded = true
|
||||
}
|
||||
s.indentState = IndentStateKeep
|
||||
ctx.resetBuffer()
|
||||
ctx.literalOpt = opt
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
err = xerrors.New("invalid literal header")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Scanner) scanNewLine(ctx *Context, c rune) {
|
||||
if len(ctx.buf) > 0 && s.savedPos == nil {
|
||||
s.savedPos = s.pos()
|
||||
s.savedPos.Column -= len(ctx.bufferedSrc())
|
||||
}
|
||||
|
||||
// if the following case, origin buffer has unnecessary two spaces.
|
||||
// So, `removeRightSpaceFromOriginBuf` remove them, also fix column number too.
|
||||
// ---
|
||||
// a:[space][space]
|
||||
// b: c
|
||||
removedNum := ctx.removeRightSpaceFromBuf()
|
||||
if removedNum > 0 {
|
||||
s.column -= removedNum
|
||||
s.offset -= removedNum
|
||||
if s.savedPos != nil {
|
||||
s.savedPos.Column -= removedNum
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.isEOS() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
} else if s.isAnchor {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
}
|
||||
ctx.addBuf(' ')
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.isSingleLine = false
|
||||
s.progressLine(ctx)
|
||||
}
|
||||
|
||||
func (s *Scanner) scan(ctx *Context) (pos int) {
|
||||
for ctx.next() {
|
||||
pos = ctx.nextPos()
|
||||
c := ctx.currentChar()
|
||||
s.updateIndent(ctx, c)
|
||||
if ctx.isDocument() {
|
||||
if s.isChangedToIndentStateEqual() ||
|
||||
s.isChangedToIndentStateDown() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
s.breakLiteral(ctx)
|
||||
} else {
|
||||
s.scanLiteral(ctx, c)
|
||||
continue
|
||||
}
|
||||
} else if s.isChangedToIndentStateDown() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
} else if s.isChangedToIndentStateEqual() {
|
||||
// if first character is new line character, buffer expect to raw folded literal
|
||||
if len(ctx.obuf) > 0 && s.newLineCount(ctx.obuf) <= 1 {
|
||||
// doesn't raw folded literal
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
}
|
||||
}
|
||||
switch c {
|
||||
case '{':
|
||||
if !ctx.existsBuffer() {
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.MappingStart(string(ctx.obuf), s.pos()))
|
||||
s.startedFlowMapNum++
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '}':
|
||||
if !ctx.existsBuffer() || s.startedFlowMapNum > 0 {
|
||||
ctx.addToken(s.bufferedToken(ctx))
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.MappingEnd(string(ctx.obuf), s.pos()))
|
||||
s.startedFlowMapNum--
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '.':
|
||||
if s.indentNum == 0 && s.column == 1 && ctx.repeatNum('.') == 3 {
|
||||
ctx.addToken(token.DocumentEnd(string(ctx.obuf)+"...", s.pos()))
|
||||
s.progressColumn(ctx, 3)
|
||||
pos += 2
|
||||
return
|
||||
}
|
||||
case '<':
|
||||
if s.isMergeKey(ctx) {
|
||||
s.prevIndentColumn = s.column
|
||||
ctx.addToken(token.MergeKey(string(ctx.obuf)+"<<", s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
pos++
|
||||
return
|
||||
}
|
||||
case '-':
|
||||
if s.indentNum == 0 && s.column == 1 && ctx.repeatNum('-') == 3 {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addToken(token.DocumentHeader(string(ctx.obuf)+"---", s.pos()))
|
||||
s.progressColumn(ctx, 3)
|
||||
pos += 2
|
||||
return
|
||||
}
|
||||
if ctx.existsBuffer() && s.isChangedToIndentStateUp() {
|
||||
// raw folded
|
||||
ctx.isRawFolded = true
|
||||
ctx.addBuf(c)
|
||||
ctx.addOriginBuf(c)
|
||||
s.progressColumn(ctx, 1)
|
||||
continue
|
||||
}
|
||||
if ctx.existsBuffer() {
|
||||
// '-' is literal
|
||||
ctx.addBuf(c)
|
||||
ctx.addOriginBuf(c)
|
||||
s.progressColumn(ctx, 1)
|
||||
continue
|
||||
}
|
||||
nc := ctx.nextChar()
|
||||
if nc == ' ' || s.isNewLineChar(nc) {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addOriginBuf(c)
|
||||
tk := token.SequenceEntry(string(ctx.obuf), s.pos())
|
||||
s.prevIndentColumn = tk.Position.Column
|
||||
ctx.addToken(tk)
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '[':
|
||||
if !ctx.existsBuffer() {
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.SequenceStart(string(ctx.obuf), s.pos()))
|
||||
s.startedFlowSequenceNum++
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case ']':
|
||||
if !ctx.existsBuffer() || s.startedFlowSequenceNum > 0 {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.SequenceEnd(string(ctx.obuf), s.pos()))
|
||||
s.startedFlowSequenceNum--
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case ',':
|
||||
if s.startedFlowSequenceNum > 0 || s.startedFlowMapNum > 0 {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.CollectEntry(string(ctx.obuf), s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case ':':
|
||||
nc := ctx.nextChar()
|
||||
if s.startedFlowMapNum > 0 || nc == ' ' || s.isNewLineChar(nc) || ctx.isNextEOS() {
|
||||
// mapping value
|
||||
tk := s.bufferedToken(ctx)
|
||||
if tk != nil {
|
||||
s.prevIndentColumn = tk.Position.Column
|
||||
ctx.addToken(tk)
|
||||
} else if tk := ctx.lastToken(); tk != nil {
|
||||
// If the map key is quote, the buffer does not exist because it has already been cut into tokens.
|
||||
// Therefore, we need to check the last token.
|
||||
if tk.Indicator == token.QuotedScalarIndicator {
|
||||
s.prevIndentColumn = tk.Position.Column
|
||||
}
|
||||
}
|
||||
ctx.addToken(token.MappingValue(s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '|', '>':
|
||||
if !ctx.existsBuffer() {
|
||||
progress, err := s.scanLiteralHeader(ctx)
|
||||
if err != nil {
|
||||
// TODO: returns syntax error object
|
||||
return
|
||||
}
|
||||
s.progressColumn(ctx, progress)
|
||||
s.progressLine(ctx)
|
||||
continue
|
||||
}
|
||||
case '!':
|
||||
if !ctx.existsBuffer() {
|
||||
token, progress := s.scanTag(ctx)
|
||||
ctx.addToken(token)
|
||||
s.progressColumn(ctx, progress)
|
||||
if c := ctx.previousChar(); s.isNewLineChar(c) {
|
||||
s.progressLine(ctx)
|
||||
}
|
||||
pos += progress
|
||||
return
|
||||
}
|
||||
case '%':
|
||||
if !ctx.existsBuffer() && s.indentNum == 0 {
|
||||
ctx.addToken(token.Directive(string(ctx.obuf)+"%", s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '?':
|
||||
nc := ctx.nextChar()
|
||||
if !ctx.existsBuffer() && nc == ' ' {
|
||||
ctx.addToken(token.MappingKey(s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '&':
|
||||
if !ctx.existsBuffer() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.Anchor(string(ctx.obuf), s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
s.isAnchor = true
|
||||
return
|
||||
}
|
||||
case '*':
|
||||
if !ctx.existsBuffer() {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
ctx.addOriginBuf(c)
|
||||
ctx.addToken(token.Alias(string(ctx.obuf), s.pos()))
|
||||
s.progressColumn(ctx, 1)
|
||||
return
|
||||
}
|
||||
case '#':
|
||||
if !ctx.existsBuffer() || ctx.previousChar() == ' ' {
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
token, progress := s.scanComment(ctx)
|
||||
ctx.addToken(token)
|
||||
s.progressColumn(ctx, progress)
|
||||
s.progressLine(ctx)
|
||||
pos += progress
|
||||
return
|
||||
}
|
||||
case '\'', '"':
|
||||
if !ctx.existsBuffer() {
|
||||
token, progress := s.scanQuote(ctx, c)
|
||||
ctx.addToken(token)
|
||||
pos += progress
|
||||
// If the non-whitespace character immediately following the quote is ':', the quote should be treated as a map key.
|
||||
// Therefore, do not return and continue processing as a normal map key.
|
||||
if ctx.currentCharWithSkipWhitespace() == ':' {
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
case '\r', '\n':
|
||||
// There is no problem that we ignore CR which followed by LF and normalize it to LF, because of following YAML1.2 spec.
|
||||
// > Line breaks inside scalar content must be normalized by the YAML processor. Each such line break must be parsed into a single line feed character.
|
||||
// > Outside scalar content, YAML allows any line break to be used to terminate lines.
|
||||
// > -- https://yaml.org/spec/1.2/spec.html
|
||||
if c == '\r' && ctx.nextChar() == '\n' {
|
||||
ctx.addOriginBuf('\r')
|
||||
ctx.progress(1)
|
||||
c = '\n'
|
||||
}
|
||||
s.scanNewLine(ctx, c)
|
||||
continue
|
||||
case ' ':
|
||||
if ctx.isSaveIndentMode() || (!s.isAnchor && !s.isFirstCharAtLine) {
|
||||
ctx.addBuf(c)
|
||||
ctx.addOriginBuf(c)
|
||||
s.progressColumn(ctx, 1)
|
||||
continue
|
||||
}
|
||||
if s.isFirstCharAtLine {
|
||||
s.progressColumn(ctx, 1)
|
||||
ctx.addOriginBuf(c)
|
||||
continue
|
||||
}
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
pos-- // to rescan white space at next scanning for adding white space to next buffer.
|
||||
s.isAnchor = false
|
||||
return
|
||||
}
|
||||
ctx.addBuf(c)
|
||||
ctx.addOriginBuf(c)
|
||||
s.progressColumn(ctx, 1)
|
||||
}
|
||||
s.addBufferedTokenIfExists(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// Init prepares the scanner s to tokenize the text src by setting the scanner at the beginning of src.
|
||||
func (s *Scanner) Init(text string) {
|
||||
src := []rune(text)
|
||||
s.source = src
|
||||
s.sourcePos = 0
|
||||
s.sourceSize = len(src)
|
||||
s.line = 1
|
||||
s.column = 1
|
||||
s.offset = 1
|
||||
s.prevIndentLevel = 0
|
||||
s.prevIndentNum = 0
|
||||
s.prevIndentColumn = 0
|
||||
s.indentLevel = 0
|
||||
s.indentNum = 0
|
||||
s.isFirstCharAtLine = true
|
||||
}
|
||||
|
||||
// Scan scans the next token and returns the token collection. The source end is indicated by io.EOF.
|
||||
func (s *Scanner) Scan() (token.Tokens, error) {
|
||||
if s.sourcePos >= s.sourceSize {
|
||||
return nil, io.EOF
|
||||
}
|
||||
ctx := newContext(s.source[s.sourcePos:])
|
||||
defer ctx.release()
|
||||
progress := s.scan(ctx)
|
||||
s.sourcePos += progress
|
||||
var tokens token.Tokens
|
||||
tokens = append(tokens, ctx.tokens...)
|
||||
return tokens, nil
|
||||
}
|
||||
103
vendor/github.com/goccy/go-yaml/stdlib_quote.go
generated
vendored
Normal file
103
vendor/github.com/goccy/go-yaml/stdlib_quote.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copied and trimmed down from https://github.com/golang/go/blob/e3769299cd3484e018e0e2a6e1b95c2b18ce4f41/src/strconv/quote.go
|
||||
// We want to use the standard library's private "quoteWith" function rather than write our own so that we get robust unicode support.
|
||||
// Every private function called by quoteWith was copied.
|
||||
// There are 2 modifications to simplify the code:
|
||||
// 1. The unicode.IsPrint function was substituted for the custom implementation of IsPrint
|
||||
// 2. All code paths reachable only when ASCIIonly or grphicOnly are set to true were removed.
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
lowerhex = "0123456789abcdef"
|
||||
)
|
||||
|
||||
func quoteWith(s string, quote byte) string {
|
||||
return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote))
|
||||
}
|
||||
|
||||
func appendQuotedWith(buf []byte, s string, quote byte) []byte {
|
||||
// Often called with big strings, so preallocate. If there's quoting,
|
||||
// this is conservative but still helps a lot.
|
||||
if cap(buf)-len(buf) < len(s) {
|
||||
nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1)
|
||||
copy(nBuf, buf)
|
||||
buf = nBuf
|
||||
}
|
||||
buf = append(buf, quote)
|
||||
for width := 0; len(s) > 0; s = s[width:] {
|
||||
r := rune(s[0])
|
||||
width = 1
|
||||
if r >= utf8.RuneSelf {
|
||||
r, width = utf8.DecodeRuneInString(s)
|
||||
}
|
||||
if width == 1 && r == utf8.RuneError {
|
||||
buf = append(buf, `\x`...)
|
||||
buf = append(buf, lowerhex[s[0]>>4])
|
||||
buf = append(buf, lowerhex[s[0]&0xF])
|
||||
continue
|
||||
}
|
||||
buf = appendEscapedRune(buf, r, quote)
|
||||
}
|
||||
buf = append(buf, quote)
|
||||
return buf
|
||||
}
|
||||
|
||||
func appendEscapedRune(buf []byte, r rune, quote byte) []byte {
|
||||
var runeTmp [utf8.UTFMax]byte
|
||||
if r == rune(quote) || r == '\\' { // always backslashed
|
||||
buf = append(buf, '\\')
|
||||
buf = append(buf, byte(r))
|
||||
return buf
|
||||
}
|
||||
if unicode.IsPrint(r) {
|
||||
n := utf8.EncodeRune(runeTmp[:], r)
|
||||
buf = append(buf, runeTmp[:n]...)
|
||||
return buf
|
||||
}
|
||||
switch r {
|
||||
case '\a':
|
||||
buf = append(buf, `\a`...)
|
||||
case '\b':
|
||||
buf = append(buf, `\b`...)
|
||||
case '\f':
|
||||
buf = append(buf, `\f`...)
|
||||
case '\n':
|
||||
buf = append(buf, `\n`...)
|
||||
case '\r':
|
||||
buf = append(buf, `\r`...)
|
||||
case '\t':
|
||||
buf = append(buf, `\t`...)
|
||||
case '\v':
|
||||
buf = append(buf, `\v`...)
|
||||
default:
|
||||
switch {
|
||||
case r < ' ':
|
||||
buf = append(buf, `\x`...)
|
||||
buf = append(buf, lowerhex[byte(r)>>4])
|
||||
buf = append(buf, lowerhex[byte(r)&0xF])
|
||||
case r > utf8.MaxRune:
|
||||
r = 0xFFFD
|
||||
fallthrough
|
||||
case r < 0x10000:
|
||||
buf = append(buf, `\u`...)
|
||||
for s := 12; s >= 0; s -= 4 {
|
||||
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
||||
}
|
||||
default:
|
||||
buf = append(buf, `\U`...)
|
||||
for s := 28; s >= 0; s -= 4 {
|
||||
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf
|
||||
}
|
||||
130
vendor/github.com/goccy/go-yaml/struct.go
generated
vendored
Normal file
130
vendor/github.com/goccy/go-yaml/struct.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
// StructTagName tag keyword for Marshal/Unmarshal
|
||||
StructTagName = "yaml"
|
||||
)
|
||||
|
||||
// StructField information for each the field in structure
|
||||
type StructField struct {
|
||||
FieldName string
|
||||
RenderName string
|
||||
AnchorName string
|
||||
AliasName string
|
||||
IsAutoAnchor bool
|
||||
IsAutoAlias bool
|
||||
IsOmitEmpty bool
|
||||
IsFlow bool
|
||||
IsInline bool
|
||||
}
|
||||
|
||||
func getTag(field reflect.StructField) string {
|
||||
// If struct tag `yaml` exist, use that. If no `yaml`
|
||||
// exists, but `json` does, use that and try the best to
|
||||
// adhere to its rules
|
||||
tag := field.Tag.Get(StructTagName)
|
||||
if tag == "" {
|
||||
tag = field.Tag.Get(`json`)
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func structField(field reflect.StructField) *StructField {
|
||||
tag := getTag(field)
|
||||
fieldName := strings.ToLower(field.Name)
|
||||
options := strings.Split(tag, ",")
|
||||
if len(options) > 0 {
|
||||
if options[0] != "" {
|
||||
fieldName = options[0]
|
||||
}
|
||||
}
|
||||
structField := &StructField{
|
||||
FieldName: field.Name,
|
||||
RenderName: fieldName,
|
||||
}
|
||||
if len(options) > 1 {
|
||||
for _, opt := range options[1:] {
|
||||
switch {
|
||||
case opt == "omitempty":
|
||||
structField.IsOmitEmpty = true
|
||||
case opt == "flow":
|
||||
structField.IsFlow = true
|
||||
case opt == "inline":
|
||||
structField.IsInline = true
|
||||
case strings.HasPrefix(opt, "anchor"):
|
||||
anchor := strings.Split(opt, "=")
|
||||
if len(anchor) > 1 {
|
||||
structField.AnchorName = anchor[1]
|
||||
} else {
|
||||
structField.IsAutoAnchor = true
|
||||
}
|
||||
case strings.HasPrefix(opt, "alias"):
|
||||
alias := strings.Split(opt, "=")
|
||||
if len(alias) > 1 {
|
||||
structField.AliasName = alias[1]
|
||||
} else {
|
||||
structField.IsAutoAlias = true
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
return structField
|
||||
}
|
||||
|
||||
func isIgnoredStructField(field reflect.StructField) bool {
|
||||
if field.PkgPath != "" && !field.Anonymous {
|
||||
// private field
|
||||
return true
|
||||
}
|
||||
tag := getTag(field)
|
||||
if tag == "-" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type StructFieldMap map[string]*StructField
|
||||
|
||||
func (m StructFieldMap) isIncludedRenderName(name string) bool {
|
||||
for _, v := range m {
|
||||
if !v.IsInline && v.RenderName == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m StructFieldMap) hasMergeProperty() bool {
|
||||
for _, v := range m {
|
||||
if v.IsOmitEmpty && v.IsInline && v.IsAutoAlias {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func structFieldMap(structType reflect.Type) (StructFieldMap, error) {
|
||||
structFieldMap := StructFieldMap{}
|
||||
renderNameMap := map[string]struct{}{}
|
||||
for i := 0; i < structType.NumField(); i++ {
|
||||
field := structType.Field(i)
|
||||
if isIgnoredStructField(field) {
|
||||
continue
|
||||
}
|
||||
structField := structField(field)
|
||||
if _, exists := renderNameMap[structField.RenderName]; exists {
|
||||
return nil, xerrors.Errorf("duplicated struct field name %s", structField.RenderName)
|
||||
}
|
||||
structFieldMap[structField.FieldName] = structField
|
||||
renderNameMap[structField.RenderName] = struct{}{}
|
||||
}
|
||||
return structFieldMap, nil
|
||||
}
|
||||
1070
vendor/github.com/goccy/go-yaml/token/token.go
generated
vendored
Normal file
1070
vendor/github.com/goccy/go-yaml/token/token.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
vendor/github.com/goccy/go-yaml/validate.go
generated
vendored
Normal file
13
vendor/github.com/goccy/go-yaml/validate.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package yaml
|
||||
|
||||
// StructValidator need to implement Struct method only
|
||||
// ( see https://pkg.go.dev/github.com/go-playground/validator/v10#Validate.Struct )
|
||||
type StructValidator interface {
|
||||
Struct(interface{}) error
|
||||
}
|
||||
|
||||
// FieldError need to implement StructField method only
|
||||
// ( see https://pkg.go.dev/github.com/go-playground/validator/v10#FieldError )
|
||||
type FieldError interface {
|
||||
StructField() string
|
||||
}
|
||||
290
vendor/github.com/goccy/go-yaml/yaml.go
generated
vendored
Normal file
290
vendor/github.com/goccy/go-yaml/yaml.go
generated
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/goccy/go-yaml/ast"
|
||||
"github.com/goccy/go-yaml/internal/errors"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// BytesMarshaler interface may be implemented by types to customize their
|
||||
// behavior when being marshaled into a YAML document. The returned value
|
||||
// is marshaled in place of the original value implementing Marshaler.
|
||||
//
|
||||
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||
// and returns with the provided error.
|
||||
type BytesMarshaler interface {
|
||||
MarshalYAML() ([]byte, error)
|
||||
}
|
||||
|
||||
// BytesMarshalerContext interface use BytesMarshaler with context.Context.
|
||||
type BytesMarshalerContext interface {
|
||||
MarshalYAML(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
// InterfaceMarshaler interface has MarshalYAML compatible with github.com/go-yaml/yaml package.
|
||||
type InterfaceMarshaler interface {
|
||||
MarshalYAML() (interface{}, error)
|
||||
}
|
||||
|
||||
// InterfaceMarshalerContext interface use InterfaceMarshaler with context.Context.
|
||||
type InterfaceMarshalerContext interface {
|
||||
MarshalYAML(context.Context) (interface{}, error)
|
||||
}
|
||||
|
||||
// BytesUnmarshaler interface may be implemented by types to customize their
|
||||
// behavior when being unmarshaled from a YAML document.
|
||||
type BytesUnmarshaler interface {
|
||||
UnmarshalYAML([]byte) error
|
||||
}
|
||||
|
||||
// BytesUnmarshalerContext interface use BytesUnmarshaler with context.Context.
|
||||
type BytesUnmarshalerContext interface {
|
||||
UnmarshalYAML(context.Context, []byte) error
|
||||
}
|
||||
|
||||
// InterfaceUnmarshaler interface has UnmarshalYAML compatible with github.com/go-yaml/yaml package.
|
||||
type InterfaceUnmarshaler interface {
|
||||
UnmarshalYAML(func(interface{}) error) error
|
||||
}
|
||||
|
||||
// InterfaceUnmarshalerContext interface use InterfaceUnmarshaler with context.Context.
|
||||
type InterfaceUnmarshalerContext interface {
|
||||
UnmarshalYAML(context.Context, func(interface{}) error) error
|
||||
}
|
||||
|
||||
// MapItem is an item in a MapSlice.
|
||||
type MapItem struct {
|
||||
Key, Value interface{}
|
||||
}
|
||||
|
||||
// MapSlice encodes and decodes as a YAML map.
|
||||
// The order of keys is preserved when encoding and decoding.
|
||||
type MapSlice []MapItem
|
||||
|
||||
// ToMap convert to map[interface{}]interface{}.
|
||||
func (s MapSlice) ToMap() map[interface{}]interface{} {
|
||||
v := map[interface{}]interface{}{}
|
||||
for _, item := range s {
|
||||
v[item.Key] = item.Value
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Marshal serializes the value provided into a YAML document. The structure
|
||||
// of the generated document will reflect the structure of the value itself.
|
||||
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||
//
|
||||
// Struct fields are only marshalled if they are exported (have an upper case
|
||||
// first letter), and are marshalled using the field name lowercased as the
|
||||
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||
// tag: the content preceding the first comma is used as the key, and the
|
||||
// following comma-separated options are used to tweak the marshalling process.
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// The field tag format accepted is:
|
||||
//
|
||||
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||
//
|
||||
// The following flags are currently supported:
|
||||
//
|
||||
// omitempty Only include the field if it's not set to the zero
|
||||
// value for the type or to empty slices or maps.
|
||||
// Zero valued structs will be omitted if all their public
|
||||
// fields are zero, unless they implement an IsZero
|
||||
// method (see the IsZeroer interface type), in which
|
||||
// case the field will be included if that method returns true.
|
||||
//
|
||||
// flow Marshal using a flow style (useful for structs,
|
||||
// sequences and maps).
|
||||
//
|
||||
// inline Inline the field, which must be a struct or a map,
|
||||
// causing all of its fields or keys to be processed as if
|
||||
// they were part of the outer struct. For maps, keys must
|
||||
// not conflict with the yaml keys of other struct fields.
|
||||
//
|
||||
// anchor Marshal with anchor. If want to define anchor name explicitly, use anchor=name style.
|
||||
// Otherwise, if used 'anchor' name only, used the field name lowercased as the anchor name
|
||||
//
|
||||
// alias Marshal with alias. If want to define alias name explicitly, use alias=name style.
|
||||
// Otherwise, If omitted alias name and the field type is pointer type,
|
||||
// assigned anchor name automatically from same pointer address.
|
||||
//
|
||||
// In addition, if the key is "-", the field is ignored.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||
// yaml.Marshal(&T{F: 1}) // Returns "a: 1\nb: 0\n"
|
||||
//
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
return MarshalWithOptions(v)
|
||||
}
|
||||
|
||||
// MarshalWithOptions serializes the value provided into a YAML document with EncodeOptions.
|
||||
func MarshalWithOptions(v interface{}, opts ...EncodeOption) ([]byte, error) {
|
||||
return MarshalContext(context.Background(), v, opts...)
|
||||
}
|
||||
|
||||
// MarshalContext serializes the value provided into a YAML document with context.Context and EncodeOptions.
|
||||
func MarshalContext(ctx context.Context, v interface{}, opts ...EncodeOption) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := NewEncoder(&buf, opts...).EncodeContext(ctx, v); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal")
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// ValueToNode convert from value to ast.Node.
|
||||
func ValueToNode(v interface{}, opts ...EncodeOption) (ast.Node, error) {
|
||||
var buf bytes.Buffer
|
||||
node, err := NewEncoder(&buf, opts...).EncodeToNode(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to convert value to node")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes the first document found within the in byte slice
|
||||
// and assigns decoded values into the out value.
|
||||
//
|
||||
// Struct fields are only unmarshalled if they are exported (have an
|
||||
// upper case first letter), and are unmarshalled using the field name
|
||||
// lowercased as the default key. Custom keys may be defined via the
|
||||
// "yaml" name in the field tag: the content preceding the first comma
|
||||
// is used as the key, and the following comma-separated options are
|
||||
// used to tweak the marshalling process (see Marshal).
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// var t T
|
||||
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||
//
|
||||
// See the documentation of Marshal for the format of tags and a list of
|
||||
// supported tag options.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
return UnmarshalWithOptions(data, v)
|
||||
}
|
||||
|
||||
// UnmarshalWithOptions decodes with DecodeOptions the first document found within the in byte slice
|
||||
// and assigns decoded values into the out value.
|
||||
func UnmarshalWithOptions(data []byte, v interface{}, opts ...DecodeOption) error {
|
||||
return UnmarshalContext(context.Background(), data, v, opts...)
|
||||
}
|
||||
|
||||
// UnmarshalContext decodes with context.Context and DecodeOptions.
|
||||
func UnmarshalContext(ctx context.Context, data []byte, v interface{}, opts ...DecodeOption) error {
|
||||
dec := NewDecoder(bytes.NewBuffer(data), opts...)
|
||||
if err := dec.DecodeContext(ctx, v); err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "failed to unmarshal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NodeToValue converts node to the value pointed to by v.
|
||||
func NodeToValue(node ast.Node, v interface{}, opts ...DecodeOption) error {
|
||||
var buf bytes.Buffer
|
||||
if err := NewDecoder(&buf, opts...).DecodeFromNode(node, v); err != nil {
|
||||
return errors.Wrapf(err, "failed to convert node to value")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatError is a utility function that takes advantage of the metadata
|
||||
// stored in the errors returned by this package's parser.
|
||||
//
|
||||
// If the second argument `colored` is true, the error message is colorized.
|
||||
// If the third argument `inclSource` is true, the error message will
|
||||
// contain snippets of the YAML source that was used.
|
||||
func FormatError(e error, colored, inclSource bool) string {
|
||||
var pp errors.PrettyPrinter
|
||||
if xerrors.As(e, &pp) {
|
||||
var buf bytes.Buffer
|
||||
pp.PrettyPrint(&errors.Sink{&buf}, colored, inclSource)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
return e.Error()
|
||||
}
|
||||
|
||||
// YAMLToJSON convert YAML bytes to JSON.
|
||||
func YAMLToJSON(bytes []byte) ([]byte, error) {
|
||||
var v interface{}
|
||||
if err := UnmarshalWithOptions(bytes, &v, UseOrderedMap()); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal")
|
||||
}
|
||||
out, err := MarshalWithOptions(v, JSON())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal with json option")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// JSONToYAML convert JSON bytes to YAML.
|
||||
func JSONToYAML(bytes []byte) ([]byte, error) {
|
||||
var v interface{}
|
||||
if err := UnmarshalWithOptions(bytes, &v, UseOrderedMap()); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal from json bytes")
|
||||
}
|
||||
out, err := Marshal(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
var (
|
||||
globalCustomMarshalerMu sync.Mutex
|
||||
globalCustomUnmarshalerMu sync.Mutex
|
||||
globalCustomMarshalerMap = map[reflect.Type]func(interface{}) ([]byte, error){}
|
||||
globalCustomUnmarshalerMap = map[reflect.Type]func(interface{}, []byte) error{}
|
||||
)
|
||||
|
||||
// RegisterCustomMarshaler overrides any encoding process for the type specified in generics.
|
||||
// If you want to switch the behavior for each encoder, use `CustomMarshaler` defined as EncodeOption.
|
||||
//
|
||||
// NOTE: If type T implements MarshalYAML for pointer receiver, the type specified in RegisterCustomMarshaler must be *T.
|
||||
// If RegisterCustomMarshaler and CustomMarshaler of EncodeOption are specified for the same type,
|
||||
// the CustomMarshaler specified in EncodeOption takes precedence.
|
||||
func RegisterCustomMarshaler[T any](marshaler func(T) ([]byte, error)) {
|
||||
globalCustomMarshalerMu.Lock()
|
||||
defer globalCustomMarshalerMu.Unlock()
|
||||
|
||||
var typ T
|
||||
globalCustomMarshalerMap[reflect.TypeOf(typ)] = func(v interface{}) ([]byte, error) {
|
||||
return marshaler(v.(T))
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCustomUnmarshaler overrides any decoding process for the type specified in generics.
|
||||
// If you want to switch the behavior for each decoder, use `CustomUnmarshaler` defined as DecodeOption.
|
||||
//
|
||||
// NOTE: If RegisterCustomUnmarshaler and CustomUnmarshaler of DecodeOption are specified for the same type,
|
||||
// the CustomUnmarshaler specified in DecodeOption takes precedence.
|
||||
func RegisterCustomUnmarshaler[T any](unmarshaler func(*T, []byte) error) {
|
||||
globalCustomUnmarshalerMu.Lock()
|
||||
defer globalCustomUnmarshalerMu.Unlock()
|
||||
|
||||
var typ *T
|
||||
globalCustomUnmarshalerMap[reflect.TypeOf(typ)] = func(v interface{}, b []byte) error {
|
||||
return unmarshaler(v.(*T), b)
|
||||
}
|
||||
}
|
||||
1
vendor/github.com/gookit/color/README.md
generated
vendored
1
vendor/github.com/gookit/color/README.md
generated
vendored
@@ -570,6 +570,7 @@ Check out these projects, which use https://github.com/gookit/color :
|
||||
- [xo/terminfo](https://github.com/xo/terminfo)
|
||||
- [beego/bee](https://github.com/beego/bee)
|
||||
- [issue9/term](https://github.com/issue9/term)
|
||||
- [muesli/termenv](https://github.com/muesli/termenv)
|
||||
- [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code)
|
||||
- [Standard ANSI color map](https://conemu.github.io/en/AnsiEscapeCodes.html#Standard_ANSI_color_map)
|
||||
- [Terminal Colors](https://gist.github.com/XVilka/8346728)
|
||||
|
||||
1
vendor/github.com/gookit/color/README.zh-CN.md
generated
vendored
1
vendor/github.com/gookit/color/README.zh-CN.md
generated
vendored
@@ -578,6 +578,7 @@ const (
|
||||
## 参考项目
|
||||
|
||||
- [inhere/console](https://github.com/inhere/php-console)
|
||||
- [muesli/termenv](https://github.com/muesli/termenv)
|
||||
- [xo/terminfo](https://github.com/xo/terminfo)
|
||||
- [beego/bee](https://github.com/beego/bee)
|
||||
- [issue9/term](https://github.com/issue9/term)
|
||||
|
||||
6
vendor/github.com/gookit/color/any.go
generated
vendored
Normal file
6
vendor/github.com/gookit/color/any.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package color
|
||||
|
||||
type any = interface{}
|
||||
4
vendor/github.com/gookit/color/color.go
generated
vendored
4
vendor/github.com/gookit/color/color.go
generated
vendored
@@ -183,7 +183,7 @@ func InnerErrs() []error {
|
||||
// Usage:
|
||||
//
|
||||
// msg := RenderCode("3;32;45", "some", "message")
|
||||
func RenderCode(code string, args ...interface{}) string {
|
||||
func RenderCode(code string, args ...any) string {
|
||||
var message string
|
||||
if ln := len(args); ln == 0 {
|
||||
return ""
|
||||
@@ -205,7 +205,7 @@ func RenderCode(code string, args ...interface{}) string {
|
||||
|
||||
// RenderWithSpaces Render code with spaces.
|
||||
// If the number of args is > 1, a space will be added between the args
|
||||
func RenderWithSpaces(code string, args ...interface{}) string {
|
||||
func RenderWithSpaces(code string, args ...any) string {
|
||||
msg := formatArgsForPrintln(args)
|
||||
if len(code) == 0 {
|
||||
return msg
|
||||
|
||||
55
vendor/github.com/gookit/color/color_16.go
generated
vendored
55
vendor/github.com/gookit/color/color_16.go
generated
vendored
@@ -188,57 +188,65 @@ func (c Color) Text(message string) string { return RenderString(c.String(), mes
|
||||
// Render messages by color setting
|
||||
//
|
||||
// Usage:
|
||||
// green := color.FgGreen.Render
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Render(a ...interface{}) string { return RenderCode(c.String(), a...) }
|
||||
//
|
||||
// green := color.FgGreen.Render
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Render(a ...any) string { return RenderCode(c.String(), a...) }
|
||||
|
||||
// Renderln messages by color setting.
|
||||
// like Println, will add spaces for each argument
|
||||
//
|
||||
// Usage:
|
||||
// green := color.FgGreen.Renderln
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Renderln(a ...interface{}) string { return RenderWithSpaces(c.String(), a...) }
|
||||
//
|
||||
// green := color.FgGreen.Renderln
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Renderln(a ...any) string { return RenderWithSpaces(c.String(), a...) }
|
||||
|
||||
// Sprint render messages by color setting. is alias of the Render()
|
||||
func (c Color) Sprint(a ...interface{}) string { return RenderCode(c.String(), a...) }
|
||||
func (c Color) Sprint(a ...any) string { return RenderCode(c.String(), a...) }
|
||||
|
||||
// Sprintf format and render message.
|
||||
//
|
||||
// Usage:
|
||||
// green := color.Green.Sprintf
|
||||
// colored := green("message")
|
||||
func (c Color) Sprintf(format string, args ...interface{}) string {
|
||||
//
|
||||
// green := color.Green.Sprintf
|
||||
// colored := green("message")
|
||||
func (c Color) Sprintf(format string, args ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Print messages.
|
||||
//
|
||||
// Usage:
|
||||
// color.Green.Print("message")
|
||||
//
|
||||
// color.Green.Print("message")
|
||||
//
|
||||
// OR:
|
||||
// green := color.FgGreen.Print
|
||||
// green("message")
|
||||
func (c Color) Print(args ...interface{}) {
|
||||
//
|
||||
// green := color.FgGreen.Print
|
||||
// green("message")
|
||||
func (c Color) Print(args ...any) {
|
||||
doPrintV2(c.Code(), fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Printf format and print messages.
|
||||
//
|
||||
// Usage:
|
||||
// color.Cyan.Printf("string %s", "arg0")
|
||||
func (c Color) Printf(format string, a ...interface{}) {
|
||||
//
|
||||
// color.Cyan.Printf("string %s", "arg0")
|
||||
func (c Color) Printf(format string, a ...any) {
|
||||
doPrintV2(c.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println messages with new line
|
||||
func (c Color) Println(a ...interface{}) { doPrintlnV2(c.String(), a) }
|
||||
func (c Color) Println(a ...any) { doPrintlnV2(c.String(), a) }
|
||||
|
||||
// Light current color. eg: 36(FgCyan) -> 96(FgLightCyan).
|
||||
//
|
||||
// Usage:
|
||||
// lightCyan := Cyan.Light()
|
||||
// lightCyan.Print("message")
|
||||
//
|
||||
// lightCyan := Cyan.Light()
|
||||
// lightCyan.Print("message")
|
||||
func (c Color) Light() Color {
|
||||
val := int(c)
|
||||
if val >= 30 && val <= 47 {
|
||||
@@ -252,8 +260,9 @@ func (c Color) Light() Color {
|
||||
// Darken current color. eg. 96(FgLightCyan) -> 36(FgCyan)
|
||||
//
|
||||
// Usage:
|
||||
// cyan := LightCyan.Darken()
|
||||
// cyan.Print("message")
|
||||
//
|
||||
// cyan := LightCyan.Darken()
|
||||
// cyan.Print("message")
|
||||
func (c Color) Darken() Color {
|
||||
val := int(c)
|
||||
if val >= 90 && val <= 107 {
|
||||
@@ -461,9 +470,7 @@ func Fg2Bg(val uint8) uint8 {
|
||||
}
|
||||
|
||||
// Basic2nameMap data
|
||||
func Basic2nameMap() map[uint8]string {
|
||||
return basic2nameMap
|
||||
}
|
||||
func Basic2nameMap() map[uint8]string { return basic2nameMap }
|
||||
|
||||
// func initName2basicMap() map[string]uint8 {
|
||||
// n2b := make(map[string]uint8, len(basic2nameMap))
|
||||
|
||||
52
vendor/github.com/gookit/color/color_256.go
generated
vendored
52
vendor/github.com/gookit/color/color_256.go
generated
vendored
@@ -19,16 +19,19 @@ from wikipedia, 256 color:
|
||||
// tpl for 8 bit 256 color(`2^8`)
|
||||
//
|
||||
// format:
|
||||
// ESC[ … 38;5;<n> … m // 选择前景色
|
||||
// ESC[ … 48;5;<n> … m // 选择背景色
|
||||
//
|
||||
// ESC[ … 38;5;<n> … m // 选择前景色
|
||||
// ESC[ … 48;5;<n> … m // 选择背景色
|
||||
//
|
||||
// example:
|
||||
// fg "\x1b[38;5;242m"
|
||||
// bg "\x1b[48;5;208m"
|
||||
// both "\x1b[38;5;242;48;5;208m"
|
||||
//
|
||||
// fg "\x1b[38;5;242m"
|
||||
// bg "\x1b[48;5;208m"
|
||||
// both "\x1b[38;5;242;48;5;208m"
|
||||
//
|
||||
// links:
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位
|
||||
//
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位
|
||||
const (
|
||||
TplFg256 = "38;5;%d"
|
||||
TplBg256 = "48;5;%d"
|
||||
@@ -45,12 +48,14 @@ const (
|
||||
// 颜色值使用10进制和16进制都可 0x98 = 152
|
||||
//
|
||||
// The color consists of two uint8:
|
||||
// 0: color value
|
||||
// 1: color type; Fg=0, Bg=1, >1: unset value
|
||||
//
|
||||
// 0: color value
|
||||
// 1: color type; Fg=0, Bg=1, >1: unset value
|
||||
//
|
||||
// example:
|
||||
// fg color: [152, 0]
|
||||
// bg color: [152, 1]
|
||||
//
|
||||
// fg color: [152, 0]
|
||||
// bg color: [152, 1]
|
||||
//
|
||||
// NOTICE: now support 256 color on windows CMD, PowerShell
|
||||
// lint warn - Name starts with package name
|
||||
@@ -87,27 +92,27 @@ func (c Color256) Reset() error {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (c Color256) Print(a ...interface{}) {
|
||||
func (c Color256) Print(a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (c Color256) Printf(format string, a ...interface{}) {
|
||||
func (c Color256) Printf(format string, a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (c Color256) Println(a ...interface{}) {
|
||||
func (c Color256) Println(a ...any) {
|
||||
doPrintlnV2(c.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (c Color256) Sprint(a ...interface{}) string {
|
||||
func (c Color256) Sprint(a ...any) string {
|
||||
return RenderCode(c.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (c Color256) Sprintf(format string, a ...interface{}) string {
|
||||
func (c Color256) Sprintf(format string, a ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -206,9 +211,10 @@ type Style256 struct {
|
||||
// S256 create a color256 style
|
||||
//
|
||||
// Usage:
|
||||
// s := color.S256()
|
||||
// s := color.S256(132) // fg
|
||||
// s := color.S256(132, 203) // fg and bg
|
||||
//
|
||||
// s := color.S256()
|
||||
// s := color.S256(132) // fg
|
||||
// s := color.S256(132, 203) // fg and bg
|
||||
func S256(fgAndBg ...uint8) *Style256 {
|
||||
s := &Style256{}
|
||||
vl := len(fgAndBg)
|
||||
@@ -256,27 +262,27 @@ func (s *Style256) AddOpts(opts ...Color) *Style256 {
|
||||
}
|
||||
|
||||
// Print message
|
||||
func (s *Style256) Print(a ...interface{}) {
|
||||
func (s *Style256) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (s *Style256) Printf(format string, a ...interface{}) {
|
||||
func (s *Style256) Printf(format string, a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (s *Style256) Println(a ...interface{}) {
|
||||
func (s *Style256) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (s *Style256) Sprint(a ...interface{}) string {
|
||||
func (s *Style256) Sprint(a ...any) string {
|
||||
return RenderCode(s.Code(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (s *Style256) Sprintf(format string, a ...interface{}) string {
|
||||
func (s *Style256) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
|
||||
90
vendor/github.com/gookit/color/color_rgb.go
generated
vendored
90
vendor/github.com/gookit/color/color_rgb.go
generated
vendored
@@ -8,20 +8,24 @@ import (
|
||||
|
||||
// 24 bit RGB color
|
||||
// RGB:
|
||||
// R 0-255 G 0-255 B 0-255
|
||||
// R 00-FF G 00-FF B 00-FF (16进制)
|
||||
//
|
||||
// R 0-255 G 0-255 B 0-255
|
||||
// R 00-FF G 00-FF B 00-FF (16进制)
|
||||
//
|
||||
// Format:
|
||||
// ESC[ … 38;2;<r>;<g>;<b> … m // Select RGB foreground color
|
||||
// ESC[ … 48;2;<r>;<g>;<b> … m // Choose RGB background color
|
||||
//
|
||||
// ESC[ … 38;2;<r>;<g>;<b> … m // Select RGB foreground color
|
||||
// ESC[ … 48;2;<r>;<g>;<b> … m // Choose RGB background color
|
||||
//
|
||||
// links:
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位
|
||||
//
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位
|
||||
//
|
||||
// example:
|
||||
// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m
|
||||
// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m
|
||||
// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m
|
||||
//
|
||||
// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m
|
||||
// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m
|
||||
// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m
|
||||
const (
|
||||
TplFgRGB = "38;2;%d;%d;%d"
|
||||
TplBgRGB = "48;2;%d;%d;%d"
|
||||
@@ -45,10 +49,11 @@ const (
|
||||
// The last digit represents the foreground(0), background(1), >1 is unset value
|
||||
//
|
||||
// Usage:
|
||||
// // 0, 1, 2 is R,G,B.
|
||||
// // 3rd: Fg=0, Bg=1, >1: unset value
|
||||
// RGBColor{30,144,255, 0}
|
||||
// RGBColor{30,144,255, 1}
|
||||
//
|
||||
// // 0, 1, 2 is R,G,B.
|
||||
// // 3rd: Fg=0, Bg=1, >1: unset value
|
||||
// RGBColor{30,144,255, 0}
|
||||
// RGBColor{30,144,255, 1}
|
||||
//
|
||||
// NOTICE: now support RGB color on Windows CMD, PowerShell
|
||||
type RGBColor [4]uint8
|
||||
@@ -59,9 +64,10 @@ var emptyRGBColor = RGBColor{3: 99}
|
||||
// RGB color create.
|
||||
//
|
||||
// Usage:
|
||||
// c := RGB(30,144,255)
|
||||
// c := RGB(30,144,255, true)
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGB(30,144,255)
|
||||
// c := RGB(30,144,255, true)
|
||||
// c.Print("message")
|
||||
func RGB(r, g, b uint8, isBg ...bool) RGBColor {
|
||||
rgb := RGBColor{r, g, b}
|
||||
if len(isBg) > 0 && isBg[0] {
|
||||
@@ -90,11 +96,12 @@ func RgbFromInts(rgb []int, isBg ...bool) RGBColor {
|
||||
// HEX create RGB color from a HEX color string.
|
||||
//
|
||||
// Usage:
|
||||
// c := HEX("ccc") // rgb: [204 204 204]
|
||||
// c := HEX("aabbcc") // rgb: [170 187 204]
|
||||
// c := HEX("#aabbcc")
|
||||
// c := HEX("0xaabbcc")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := HEX("ccc") // rgb: [204 204 204]
|
||||
// c := HEX("aabbcc") // rgb: [170 187 204]
|
||||
// c := HEX("#aabbcc")
|
||||
// c := HEX("0xaabbcc")
|
||||
// c.Print("message")
|
||||
func HEX(hex string, isBg ...bool) RGBColor {
|
||||
if rgb := HexToRgb(hex); len(rgb) > 0 {
|
||||
return RGB(uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), isBg...)
|
||||
@@ -139,11 +146,12 @@ func RGBFromSlice(rgb []uint8, isBg ...bool) RGBColor {
|
||||
// Support use color name in the {namedRgbMap}
|
||||
//
|
||||
// Usage:
|
||||
// c := RGBFromString("170,187,204")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGBFromString("brown")
|
||||
// c.Print("message with color brown")
|
||||
// c := RGBFromString("170,187,204")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGBFromString("brown")
|
||||
// c.Print("message with color brown")
|
||||
func RGBFromString(rgb string, isBg ...bool) RGBColor {
|
||||
// use color name in the {namedRgbMap}
|
||||
if rgbVal, ok := namedRgbMap[rgb]; ok {
|
||||
@@ -180,27 +188,27 @@ func (c RGBColor) Reset() error {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (c RGBColor) Print(a ...interface{}) {
|
||||
func (c RGBColor) Print(a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (c RGBColor) Printf(format string, a ...interface{}) {
|
||||
func (c RGBColor) Printf(format string, a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (c RGBColor) Println(a ...interface{}) {
|
||||
func (c RGBColor) Println(a ...any) {
|
||||
doPrintlnV2(c.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (c RGBColor) Sprint(a ...interface{}) string {
|
||||
func (c RGBColor) Sprint(a ...any) string {
|
||||
return RenderCode(c.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (c RGBColor) Sprintf(format string, a ...interface{}) string {
|
||||
func (c RGBColor) Sprintf(format string, a ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -279,8 +287,8 @@ func (c RGBColor) C16() Color { return c.Basic() }
|
||||
// All are composed of 4 digits uint8, the first three digits are the color value;
|
||||
// The last bit is different from RGBColor, here it indicates whether the value is set.
|
||||
//
|
||||
// 1 Has been set
|
||||
// ^1 Not set
|
||||
// 1 Has been set
|
||||
// ^1 Not set
|
||||
type RGBStyle struct {
|
||||
// Name of the style
|
||||
Name string
|
||||
@@ -303,8 +311,9 @@ func NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle {
|
||||
// HEXStyle create a RGBStyle from HEX color string.
|
||||
//
|
||||
// Usage:
|
||||
// s := HEXStyle("aabbcc", "eee")
|
||||
// s.Print("message")
|
||||
//
|
||||
// s := HEXStyle("aabbcc", "eee")
|
||||
// s.Print("message")
|
||||
func HEXStyle(fg string, bg ...string) *RGBStyle {
|
||||
s := &RGBStyle{}
|
||||
if len(bg) > 0 {
|
||||
@@ -320,8 +329,9 @@ func HEXStyle(fg string, bg ...string) *RGBStyle {
|
||||
// RGBStyleFromString create a RGBStyle from color value string.
|
||||
//
|
||||
// Usage:
|
||||
// s := RGBStyleFromString("170,187,204", "70,87,4")
|
||||
// s.Print("message")
|
||||
//
|
||||
// s := RGBStyleFromString("170,187,204", "70,87,4")
|
||||
// s.Print("message")
|
||||
func RGBStyleFromString(fg string, bg ...string) *RGBStyle {
|
||||
s := &RGBStyle{}
|
||||
if len(bg) > 0 {
|
||||
@@ -363,27 +373,27 @@ func (s *RGBStyle) AddOpts(opts ...Color) *RGBStyle {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (s *RGBStyle) Print(a ...interface{}) {
|
||||
func (s *RGBStyle) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (s *RGBStyle) Printf(format string, a ...interface{}) {
|
||||
func (s *RGBStyle) Printf(format string, a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (s *RGBStyle) Println(a ...interface{}) {
|
||||
func (s *RGBStyle) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (s *RGBStyle) Sprint(a ...interface{}) string {
|
||||
func (s *RGBStyle) Sprint(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (s *RGBStyle) Sprintf(format string, a ...interface{}) string {
|
||||
func (s *RGBStyle) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
|
||||
56
vendor/github.com/gookit/color/color_tag.go
generated
vendored
56
vendor/github.com/gookit/color/color_tag.go
generated
vendored
@@ -41,7 +41,8 @@ var (
|
||||
// There are internal defined fg color tags
|
||||
//
|
||||
// Usage:
|
||||
// <tag>content text</>
|
||||
//
|
||||
// <tag>content text</>
|
||||
//
|
||||
// @notice 加 0 在前面是为了防止之前的影响到现在的设置
|
||||
var colorTags = map[string]string{
|
||||
@@ -324,15 +325,17 @@ func (tp *TagParser) ParseByEnv(str string) string {
|
||||
return tp.Parse(str)
|
||||
}
|
||||
|
||||
// Parse parse given string, replace color tag and return rendered string
|
||||
// Parse given string, replace color tag and return rendered string
|
||||
//
|
||||
// Use built in tags:
|
||||
// <TAG_NAME>CONTENT</>
|
||||
// // e.g: `<info>message</>`
|
||||
//
|
||||
// <TAG_NAME>CONTENT</>
|
||||
// // e.g: `<info>message</>`
|
||||
//
|
||||
// Custom tag attributes:
|
||||
// `<fg=VALUE;bg=VALUE;op=VALUES>CONTENT</>`
|
||||
// // e.g: `<fg=167;bg=232>wel</>`
|
||||
//
|
||||
// `<fg=VALUE;bg=VALUE;op=VALUES>CONTENT</>`
|
||||
// // e.g: `<fg=167;bg=232>wel</>`
|
||||
func (tp *TagParser) Parse(str string) string {
|
||||
// not contains color tag
|
||||
if !strings.Contains(str, "</>") {
|
||||
@@ -376,26 +379,30 @@ func ReplaceTag(str string) string {
|
||||
// ParseCodeFromAttr parse color attributes.
|
||||
//
|
||||
// attr format:
|
||||
// // VALUE please see var: FgColors, BgColors, AllOptions
|
||||
// "fg=VALUE;bg=VALUE;op=VALUE"
|
||||
//
|
||||
// // VALUE please see var: FgColors, BgColors, AllOptions
|
||||
// "fg=VALUE;bg=VALUE;op=VALUE"
|
||||
//
|
||||
// 16 color:
|
||||
// "fg=yellow"
|
||||
// "bg=red"
|
||||
// "op=bold,underscore" // option is allow multi value
|
||||
// "fg=white;bg=blue;op=bold"
|
||||
// "fg=white;op=bold,underscore"
|
||||
//
|
||||
// "fg=yellow"
|
||||
// "bg=red"
|
||||
// "op=bold,underscore" // option is allow multi value
|
||||
// "fg=white;bg=blue;op=bold"
|
||||
// "fg=white;op=bold,underscore"
|
||||
//
|
||||
// 256 color:
|
||||
//
|
||||
// "fg=167"
|
||||
// "fg=167;bg=23"
|
||||
// "fg=167;bg=23;op=bold"
|
||||
//
|
||||
// True color:
|
||||
// // hex
|
||||
//
|
||||
// // hex
|
||||
// "fg=fc1cac"
|
||||
// "fg=fc1cac;bg=c2c3c4"
|
||||
// // r,g,b
|
||||
// // r,g,b
|
||||
// "fg=23,45,214"
|
||||
// "fg=23,45,214;bg=109,99,88"
|
||||
func ParseCodeFromAttr(attr string) (code string) {
|
||||
@@ -476,12 +483,10 @@ func ClearTag(s string) string {
|
||||
*************************************************************/
|
||||
|
||||
// GetTagCode get color code by tag name
|
||||
func GetTagCode(name string) string {
|
||||
return colorTags[name]
|
||||
}
|
||||
func GetTagCode(name string) string { return colorTags[name] }
|
||||
|
||||
// ApplyTag for messages
|
||||
func ApplyTag(tag string, a ...interface{}) string {
|
||||
func ApplyTag(tag string, a ...any) string {
|
||||
return RenderCode(GetTagCode(tag), a...)
|
||||
}
|
||||
|
||||
@@ -510,11 +515,12 @@ func IsDefinedTag(name string) bool {
|
||||
|
||||
// Tag value is a defined style name
|
||||
// Usage:
|
||||
// Tag("info").Println("message")
|
||||
//
|
||||
// Tag("info").Println("message")
|
||||
type Tag string
|
||||
|
||||
// Print messages
|
||||
func (tg Tag) Print(a ...interface{}) {
|
||||
func (tg Tag) Print(a ...any) {
|
||||
name := string(tg)
|
||||
str := fmt.Sprint(a...)
|
||||
|
||||
@@ -526,7 +532,7 @@ func (tg Tag) Print(a ...interface{}) {
|
||||
}
|
||||
|
||||
// Printf format and print messages
|
||||
func (tg Tag) Printf(format string, a ...interface{}) {
|
||||
func (tg Tag) Printf(format string, a ...any) {
|
||||
name := string(tg)
|
||||
str := fmt.Sprintf(format, a...)
|
||||
|
||||
@@ -538,7 +544,7 @@ func (tg Tag) Printf(format string, a ...interface{}) {
|
||||
}
|
||||
|
||||
// Println messages line
|
||||
func (tg Tag) Println(a ...interface{}) {
|
||||
func (tg Tag) Println(a ...any) {
|
||||
name := string(tg)
|
||||
if stl := GetStyle(name); !stl.IsEmpty() {
|
||||
stl.Println(a...)
|
||||
@@ -548,12 +554,12 @@ func (tg Tag) Println(a ...interface{}) {
|
||||
}
|
||||
|
||||
// Sprint render messages
|
||||
func (tg Tag) Sprint(a ...interface{}) string {
|
||||
func (tg Tag) Sprint(a ...any) string {
|
||||
return RenderCode(GetTagCode(string(tg)), a...)
|
||||
}
|
||||
|
||||
// Sprintf format and render messages
|
||||
func (tg Tag) Sprintf(format string, a ...interface{}) string {
|
||||
func (tg Tag) Sprintf(format string, a ...any) string {
|
||||
tag := string(tg)
|
||||
str := fmt.Sprintf(format, a...)
|
||||
|
||||
|
||||
53
vendor/github.com/gookit/color/printer.go
generated
vendored
53
vendor/github.com/gookit/color/printer.go
generated
vendored
@@ -9,18 +9,19 @@ import "fmt"
|
||||
// PrinterFace interface
|
||||
type PrinterFace interface {
|
||||
fmt.Stringer
|
||||
Sprint(a ...interface{}) string
|
||||
Sprintf(format string, a ...interface{}) string
|
||||
Print(a ...interface{})
|
||||
Printf(format string, a ...interface{})
|
||||
Println(a ...interface{})
|
||||
Sprint(a ...any) string
|
||||
Sprintf(format string, a ...any) string
|
||||
Print(a ...any)
|
||||
Printf(format string, a ...any)
|
||||
Println(a ...any)
|
||||
}
|
||||
|
||||
// Printer a generic color message printer.
|
||||
//
|
||||
// Usage:
|
||||
// p := &Printer{Code: "32;45;3"}
|
||||
// p.Print("message")
|
||||
//
|
||||
// p := &Printer{Code: "32;45;3"}
|
||||
// p.Print("message")
|
||||
type Printer struct {
|
||||
// NoColor disable color.
|
||||
NoColor bool
|
||||
@@ -40,27 +41,27 @@ func (p *Printer) String() string {
|
||||
}
|
||||
|
||||
// Sprint returns rendering colored messages
|
||||
func (p *Printer) Sprint(a ...interface{}) string {
|
||||
func (p *Printer) Sprint(a ...any) string {
|
||||
return RenderCode(p.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendering colored messages
|
||||
func (p *Printer) Sprintf(format string, a ...interface{}) string {
|
||||
func (p *Printer) Sprintf(format string, a ...any) string {
|
||||
return RenderString(p.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Print rendering colored messages
|
||||
func (p *Printer) Print(a ...interface{}) {
|
||||
func (p *Printer) Print(a ...any) {
|
||||
doPrintV2(p.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and rendering colored messages
|
||||
func (p *Printer) Printf(format string, a ...interface{}) {
|
||||
func (p *Printer) Printf(format string, a ...any) {
|
||||
doPrintV2(p.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println rendering colored messages with newline
|
||||
func (p *Printer) Println(a ...interface{}) {
|
||||
func (p *Printer) Println(a ...any) {
|
||||
doPrintlnV2(p.Code, a)
|
||||
}
|
||||
|
||||
@@ -77,46 +78,56 @@ func (p *Printer) IsEmpty() bool {
|
||||
type SimplePrinter struct{}
|
||||
|
||||
// Print message
|
||||
func (s *SimplePrinter) Print(v ...interface{}) {
|
||||
func (s *SimplePrinter) Print(v ...any) {
|
||||
Print(v...)
|
||||
}
|
||||
|
||||
// Printf message
|
||||
func (s *SimplePrinter) Printf(format string, v ...interface{}) {
|
||||
func (s *SimplePrinter) Printf(format string, v ...any) {
|
||||
Printf(format, v...)
|
||||
}
|
||||
|
||||
// Println message
|
||||
func (s *SimplePrinter) Println(v ...interface{}) {
|
||||
func (s *SimplePrinter) Println(v ...any) {
|
||||
Println(v...)
|
||||
}
|
||||
|
||||
// Successf message
|
||||
func (s *SimplePrinter) Successf(format string, a ...any) {
|
||||
Success.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Successln message
|
||||
func (s *SimplePrinter) Successln(a ...any) {
|
||||
Success.Println(a...)
|
||||
}
|
||||
|
||||
// Infof message
|
||||
func (s *SimplePrinter) Infof(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Infof(format string, a ...any) {
|
||||
Info.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Infoln message
|
||||
func (s *SimplePrinter) Infoln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Infoln(a ...any) {
|
||||
Info.Println(a...)
|
||||
}
|
||||
|
||||
// Warnf message
|
||||
func (s *SimplePrinter) Warnf(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Warnf(format string, a ...any) {
|
||||
Warn.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Warnln message
|
||||
func (s *SimplePrinter) Warnln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Warnln(a ...any) {
|
||||
Warn.Println(a...)
|
||||
}
|
||||
|
||||
// Errorf message
|
||||
func (s *SimplePrinter) Errorf(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Errorf(format string, a ...any) {
|
||||
Error.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Errorln message
|
||||
func (s *SimplePrinter) Errorln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Errorln(a ...any) {
|
||||
Error.Println(a...)
|
||||
}
|
||||
|
||||
66
vendor/github.com/gookit/color/quickstart.go
generated
vendored
66
vendor/github.com/gookit/color/quickstart.go
generated
vendored
@@ -5,104 +5,104 @@ package color
|
||||
*************************************************************/
|
||||
|
||||
// Redp print message with Red color
|
||||
func Redp(a ...interface{}) { Red.Print(a...) }
|
||||
func Redp(a ...any) { Red.Print(a...) }
|
||||
|
||||
// Redf print message with Red color
|
||||
func Redf(format string, a ...interface{}) { Red.Printf(format, a...) }
|
||||
func Redf(format string, a ...any) { Red.Printf(format, a...) }
|
||||
|
||||
// Redln print message line with Red color
|
||||
func Redln(a ...interface{}) { Red.Println(a...) }
|
||||
func Redln(a ...any) { Red.Println(a...) }
|
||||
|
||||
// Bluep print message with Blue color
|
||||
func Bluep(a ...interface{}) { Blue.Print(a...) }
|
||||
func Bluep(a ...any) { Blue.Print(a...) }
|
||||
|
||||
// Bluef print message with Blue color
|
||||
func Bluef(format string, a ...interface{}) { Blue.Printf(format, a...) }
|
||||
func Bluef(format string, a ...any) { Blue.Printf(format, a...) }
|
||||
|
||||
// Blueln print message line with Blue color
|
||||
func Blueln(a ...interface{}) { Blue.Println(a...) }
|
||||
func Blueln(a ...any) { Blue.Println(a...) }
|
||||
|
||||
// Cyanp print message with Cyan color
|
||||
func Cyanp(a ...interface{}) { Cyan.Print(a...) }
|
||||
func Cyanp(a ...any) { Cyan.Print(a...) }
|
||||
|
||||
// Cyanf print message with Cyan color
|
||||
func Cyanf(format string, a ...interface{}) { Cyan.Printf(format, a...) }
|
||||
func Cyanf(format string, a ...any) { Cyan.Printf(format, a...) }
|
||||
|
||||
// Cyanln print message line with Cyan color
|
||||
func Cyanln(a ...interface{}) { Cyan.Println(a...) }
|
||||
func Cyanln(a ...any) { Cyan.Println(a...) }
|
||||
|
||||
// Grayp print message with Gray color
|
||||
func Grayp(a ...interface{}) { Gray.Print(a...) }
|
||||
func Grayp(a ...any) { Gray.Print(a...) }
|
||||
|
||||
// Grayf print message with Gray color
|
||||
func Grayf(format string, a ...interface{}) { Gray.Printf(format, a...) }
|
||||
func Grayf(format string, a ...any) { Gray.Printf(format, a...) }
|
||||
|
||||
// Grayln print message line with Gray color
|
||||
func Grayln(a ...interface{}) { Gray.Println(a...) }
|
||||
func Grayln(a ...any) { Gray.Println(a...) }
|
||||
|
||||
// Greenp print message with Green color
|
||||
func Greenp(a ...interface{}) { Green.Print(a...) }
|
||||
func Greenp(a ...any) { Green.Print(a...) }
|
||||
|
||||
// Greenf print message with Green color
|
||||
func Greenf(format string, a ...interface{}) { Green.Printf(format, a...) }
|
||||
func Greenf(format string, a ...any) { Green.Printf(format, a...) }
|
||||
|
||||
// Greenln print message line with Green color
|
||||
func Greenln(a ...interface{}) { Green.Println(a...) }
|
||||
func Greenln(a ...any) { Green.Println(a...) }
|
||||
|
||||
// Yellowp print message with Yellow color
|
||||
func Yellowp(a ...interface{}) { Yellow.Print(a...) }
|
||||
func Yellowp(a ...any) { Yellow.Print(a...) }
|
||||
|
||||
// Yellowf print message with Yellow color
|
||||
func Yellowf(format string, a ...interface{}) { Yellow.Printf(format, a...) }
|
||||
func Yellowf(format string, a ...any) { Yellow.Printf(format, a...) }
|
||||
|
||||
// Yellowln print message line with Yellow color
|
||||
func Yellowln(a ...interface{}) { Yellow.Println(a...) }
|
||||
func Yellowln(a ...any) { Yellow.Println(a...) }
|
||||
|
||||
// Magentap print message with Magenta color
|
||||
func Magentap(a ...interface{}) { Magenta.Print(a...) }
|
||||
func Magentap(a ...any) { Magenta.Print(a...) }
|
||||
|
||||
// Magentaf print message with Magenta color
|
||||
func Magentaf(format string, a ...interface{}) { Magenta.Printf(format, a...) }
|
||||
func Magentaf(format string, a ...any) { Magenta.Printf(format, a...) }
|
||||
|
||||
// Magentaln print message line with Magenta color
|
||||
func Magentaln(a ...interface{}) { Magenta.Println(a...) }
|
||||
func Magentaln(a ...any) { Magenta.Println(a...) }
|
||||
|
||||
/*************************************************************
|
||||
* quick use style print message
|
||||
*************************************************************/
|
||||
|
||||
// Infop print message with Info color
|
||||
func Infop(a ...interface{}) { Info.Print(a...) }
|
||||
func Infop(a ...any) { Info.Print(a...) }
|
||||
|
||||
// Infof print message with Info style
|
||||
func Infof(format string, a ...interface{}) { Info.Printf(format, a...) }
|
||||
func Infof(format string, a ...any) { Info.Printf(format, a...) }
|
||||
|
||||
// Infoln print message with Info style
|
||||
func Infoln(a ...interface{}) { Info.Println(a...) }
|
||||
func Infoln(a ...any) { Info.Println(a...) }
|
||||
|
||||
// Successp print message with success color
|
||||
func Successp(a ...interface{}) { Success.Print(a...) }
|
||||
func Successp(a ...any) { Success.Print(a...) }
|
||||
|
||||
// Successf print message with success style
|
||||
func Successf(format string, a ...interface{}) { Success.Printf(format, a...) }
|
||||
func Successf(format string, a ...any) { Success.Printf(format, a...) }
|
||||
|
||||
// Successln print message with success style
|
||||
func Successln(a ...interface{}) { Success.Println(a...) }
|
||||
func Successln(a ...any) { Success.Println(a...) }
|
||||
|
||||
// Errorp print message with Error color
|
||||
func Errorp(a ...interface{}) { Error.Print(a...) }
|
||||
func Errorp(a ...any) { Error.Print(a...) }
|
||||
|
||||
// Errorf print message with Error style
|
||||
func Errorf(format string, a ...interface{}) { Error.Printf(format, a...) }
|
||||
func Errorf(format string, a ...any) { Error.Printf(format, a...) }
|
||||
|
||||
// Errorln print message with Error style
|
||||
func Errorln(a ...interface{}) { Error.Println(a...) }
|
||||
func Errorln(a ...any) { Error.Println(a...) }
|
||||
|
||||
// Warnp print message with Warn color
|
||||
func Warnp(a ...interface{}) { Warn.Print(a...) }
|
||||
func Warnp(a ...any) { Warn.Print(a...) }
|
||||
|
||||
// Warnf print message with Warn style
|
||||
func Warnf(format string, a ...interface{}) { Warn.Printf(format, a...) }
|
||||
func Warnf(format string, a ...any) { Warn.Printf(format, a...) }
|
||||
|
||||
// Warnln print message with Warn style
|
||||
func Warnln(a ...interface{}) { Warn.Println(a...) }
|
||||
func Warnln(a ...any) { Warn.Println(a...) }
|
||||
|
||||
61
vendor/github.com/gookit/color/style.go
generated
vendored
61
vendor/github.com/gookit/color/style.go
generated
vendored
@@ -12,12 +12,14 @@ import (
|
||||
// Style a 16 color style. can add: fg color, bg color, color options
|
||||
//
|
||||
// Example:
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
//
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
type Style []Color
|
||||
|
||||
// New create a custom style
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// color.New(color.FgGreen).Print("message")
|
||||
// equals to:
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
@@ -37,43 +39,45 @@ func (s *Style) Add(cs ...Color) {
|
||||
|
||||
// Render render text
|
||||
// Usage:
|
||||
// color.New(color.FgGreen).Render("text")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text")
|
||||
func (s Style) Render(a ...interface{}) string {
|
||||
//
|
||||
// color.New(color.FgGreen).Render("text")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text")
|
||||
func (s Style) Render(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Renderln render text line.
|
||||
// like Println, will add spaces for each argument
|
||||
// Usage:
|
||||
// color.New(color.FgGreen).Renderln("text", "more")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more")
|
||||
func (s Style) Renderln(a ...interface{}) string {
|
||||
//
|
||||
// color.New(color.FgGreen).Renderln("text", "more")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more")
|
||||
func (s Style) Renderln(a ...any) string {
|
||||
return RenderWithSpaces(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprint is alias of the 'Render'
|
||||
func (s Style) Sprint(a ...interface{}) string {
|
||||
func (s Style) Sprint(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf format and render message.
|
||||
func (s Style) Sprintf(format string, a ...interface{}) string {
|
||||
func (s Style) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Print render and Print text
|
||||
func (s Style) Print(a ...interface{}) {
|
||||
func (s Style) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf render and print text
|
||||
func (s Style) Printf(format string, a ...interface{}) {
|
||||
func (s Style) Printf(format string, a ...any) {
|
||||
doPrintV2(s.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println render and print text line
|
||||
func (s Style) Println(a ...interface{}) {
|
||||
func (s Style) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
@@ -115,20 +119,20 @@ func (t *Theme) Save() {
|
||||
}
|
||||
|
||||
// Tips use name as title, only apply style for name
|
||||
func (t *Theme) Tips(format string, a ...interface{}) {
|
||||
func (t *Theme) Tips(format string, a ...any) {
|
||||
// only apply style for name
|
||||
t.Print(strings.ToUpper(t.Name) + ": ")
|
||||
Printf(format+"\n", a...)
|
||||
}
|
||||
|
||||
// Prompt use name as title, and apply style for message
|
||||
func (t *Theme) Prompt(format string, a ...interface{}) {
|
||||
func (t *Theme) Prompt(format string, a ...any) {
|
||||
title := strings.ToUpper(t.Name) + ":"
|
||||
t.Println(title, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Block like Prompt, but will wrap a empty line
|
||||
func (t *Theme) Block(format string, a ...interface{}) {
|
||||
func (t *Theme) Block(format string, a ...any) {
|
||||
title := strings.ToUpper(t.Name) + ":\n"
|
||||
|
||||
t.Println(title, fmt.Sprintf(format, a...))
|
||||
@@ -140,10 +144,11 @@ func (t *Theme) Block(format string, a ...interface{}) {
|
||||
|
||||
// internal themes(like bootstrap style)
|
||||
// Usage:
|
||||
// color.Info.Print("message")
|
||||
// color.Info.Printf("a %s message", "test")
|
||||
// color.Warn.Println("message")
|
||||
// color.Error.Println("message")
|
||||
//
|
||||
// color.Info.Print("message")
|
||||
// color.Info.Printf("a %s message", "test")
|
||||
// color.Warn.Println("message")
|
||||
// color.Error.Println("message")
|
||||
var (
|
||||
// Info color style
|
||||
Info = &Theme{"info", Style{OpReset, FgGreen}}
|
||||
@@ -175,7 +180,8 @@ var (
|
||||
|
||||
// Themes internal defined themes.
|
||||
// Usage:
|
||||
// color.Themes["info"].Println("message")
|
||||
//
|
||||
// color.Themes["info"].Println("message")
|
||||
var Themes = map[string]*Theme{
|
||||
"info": Info,
|
||||
"note": Note,
|
||||
@@ -211,7 +217,8 @@ func GetTheme(name string) *Theme {
|
||||
|
||||
// Styles internal defined styles, like bootstrap styles.
|
||||
// Usage:
|
||||
// color.Styles["info"].Println("message")
|
||||
//
|
||||
// color.Styles["info"].Println("message")
|
||||
var Styles = map[string]Style{
|
||||
"info": {OpReset, FgGreen},
|
||||
"note": {OpBold, FgLightCyan},
|
||||
@@ -285,31 +292,31 @@ func (s *Scheme) Style(name string) Style {
|
||||
}
|
||||
|
||||
// Infof message print
|
||||
func (s *Scheme) Infof(format string, a ...interface{}) {
|
||||
func (s *Scheme) Infof(format string, a ...any) {
|
||||
s.Styles["info"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Infoln message print
|
||||
func (s *Scheme) Infoln(v ...interface{}) {
|
||||
func (s *Scheme) Infoln(v ...any) {
|
||||
s.Styles["info"].Println(v...)
|
||||
}
|
||||
|
||||
// Warnf message print
|
||||
func (s *Scheme) Warnf(format string, a ...interface{}) {
|
||||
func (s *Scheme) Warnf(format string, a ...any) {
|
||||
s.Styles["warn"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Warnln message print
|
||||
func (s *Scheme) Warnln(v ...interface{}) {
|
||||
func (s *Scheme) Warnln(v ...any) {
|
||||
s.Styles["warn"].Println(v...)
|
||||
}
|
||||
|
||||
// Errorf message print
|
||||
func (s *Scheme) Errorf(format string, a ...interface{}) {
|
||||
func (s *Scheme) Errorf(format string, a ...any) {
|
||||
s.Styles["error"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Errorln message print
|
||||
func (s *Scheme) Errorln(v ...interface{}) {
|
||||
func (s *Scheme) Errorln(v ...any) {
|
||||
s.Styles["error"].Println(v...)
|
||||
}
|
||||
|
||||
51
vendor/github.com/gookit/color/utils.go
generated
vendored
51
vendor/github.com/gookit/color/utils.go
generated
vendored
@@ -32,39 +32,31 @@ func ResetTerminal() error {
|
||||
*************************************************************/
|
||||
|
||||
// Print render color tag and print messages
|
||||
func Print(a ...interface{}) {
|
||||
func Print(a ...any) {
|
||||
Fprint(output, a...)
|
||||
}
|
||||
|
||||
// Printf format and print messages
|
||||
func Printf(format string, a ...interface{}) {
|
||||
func Printf(format string, a ...any) {
|
||||
Fprintf(output, format, a...)
|
||||
}
|
||||
|
||||
// Println messages with new line
|
||||
func Println(a ...interface{}) {
|
||||
func Println(a ...any) {
|
||||
Fprintln(output, a...)
|
||||
}
|
||||
|
||||
// Fprint print rendered messages to writer
|
||||
//
|
||||
// Notice: will ignore print error
|
||||
func Fprint(w io.Writer, a ...interface{}) {
|
||||
func Fprint(w io.Writer, a ...any) {
|
||||
_, err := fmt.Fprint(w, Render(a...))
|
||||
saveInternalError(err)
|
||||
|
||||
// if isLikeInCmd {
|
||||
// renderColorCodeOnCmd(func() {
|
||||
// _, _ = fmt.Fprint(w, Render(a...))
|
||||
// })
|
||||
// } else {
|
||||
// _, _ = fmt.Fprint(w, Render(a...))
|
||||
// }
|
||||
}
|
||||
|
||||
// Fprintf print format and rendered messages to writer.
|
||||
// Notice: will ignore print error
|
||||
func Fprintf(w io.Writer, format string, a ...interface{}) {
|
||||
func Fprintf(w io.Writer, format string, a ...any) {
|
||||
str := fmt.Sprintf(format, a...)
|
||||
_, err := fmt.Fprint(w, ReplaceTag(str))
|
||||
saveInternalError(err)
|
||||
@@ -72,7 +64,7 @@ func Fprintf(w io.Writer, format string, a ...interface{}) {
|
||||
|
||||
// Fprintln print rendered messages line to writer
|
||||
// Notice: will ignore print error
|
||||
func Fprintln(w io.Writer, a ...interface{}) {
|
||||
func Fprintln(w io.Writer, a ...any) {
|
||||
str := formatArgsForPrintln(a)
|
||||
_, err := fmt.Fprintln(w, ReplaceTag(str))
|
||||
saveInternalError(err)
|
||||
@@ -80,7 +72,7 @@ func Fprintln(w io.Writer, a ...interface{}) {
|
||||
|
||||
// Lprint passes colored messages to a log.Logger for printing.
|
||||
// Notice: should be goroutine safe
|
||||
func Lprint(l *log.Logger, a ...interface{}) {
|
||||
func Lprint(l *log.Logger, a ...any) {
|
||||
l.Print(Render(a...))
|
||||
}
|
||||
|
||||
@@ -90,7 +82,7 @@ func Lprint(l *log.Logger, a ...interface{}) {
|
||||
//
|
||||
// text := Render("<info>hello</> <cyan>world</>!")
|
||||
// fmt.Println(text)
|
||||
func Render(a ...interface{}) string {
|
||||
func Render(a ...any) string {
|
||||
if len(a) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -98,28 +90,23 @@ func Render(a ...interface{}) string {
|
||||
}
|
||||
|
||||
// Sprint parse color tags, return rendered string
|
||||
func Sprint(a ...interface{}) string {
|
||||
func Sprint(a ...any) string {
|
||||
if len(a) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return ReplaceTag(fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Sprintf format and return rendered string
|
||||
func Sprintf(format string, a ...interface{}) string {
|
||||
func Sprintf(format string, a ...any) string {
|
||||
return ReplaceTag(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// String alias of the ReplaceTag
|
||||
func String(s string) string {
|
||||
return ReplaceTag(s)
|
||||
}
|
||||
func String(s string) string { return ReplaceTag(s) }
|
||||
|
||||
// Text alias of the ReplaceTag
|
||||
func Text(s string) string {
|
||||
return ReplaceTag(s)
|
||||
}
|
||||
func Text(s string) string { return ReplaceTag(s) }
|
||||
|
||||
// Uint8sToInts convert []uint8 to []int
|
||||
// func Uint8sToInts(u8s []uint8 ) []int {
|
||||
@@ -138,25 +125,17 @@ func Text(s string) string {
|
||||
func doPrintV2(code, str string) {
|
||||
_, err := fmt.Fprint(output, RenderString(code, str))
|
||||
saveInternalError(err)
|
||||
|
||||
// if isLikeInCmd {
|
||||
// renderColorCodeOnCmd(func() {
|
||||
// _, _ = fmt.Fprint(output, RenderString(code, str))
|
||||
// })
|
||||
// } else {
|
||||
// _, _ = fmt.Fprint(output, RenderString(code, str))
|
||||
// }
|
||||
}
|
||||
|
||||
// new implementation, support render full color code on pwsh.exe, cmd.exe
|
||||
func doPrintlnV2(code string, args []interface{}) {
|
||||
func doPrintlnV2(code string, args []any) {
|
||||
str := formatArgsForPrintln(args)
|
||||
_, err := fmt.Fprintln(output, RenderString(code, str))
|
||||
saveInternalError(err)
|
||||
}
|
||||
|
||||
// use Println, will add spaces for each arg
|
||||
func formatArgsForPrintln(args []interface{}) (message string) {
|
||||
func formatArgsForPrintln(args []any) (message string) {
|
||||
if ln := len(args); ln == 0 {
|
||||
message = ""
|
||||
} else if ln == 1 {
|
||||
@@ -178,7 +157,7 @@ func formatArgsForPrintln(args []interface{}) (message string) {
|
||||
// return debugMode == "on"
|
||||
// }
|
||||
|
||||
func debugf(f string, v ...interface{}) {
|
||||
func debugf(f string, v ...any) {
|
||||
if debugMode {
|
||||
fmt.Print("COLOR_DEBUG: ")
|
||||
fmt.Printf(f, v...)
|
||||
|
||||
33
vendor/github.com/gookit/config/v2/README.md
generated
vendored
33
vendor/github.com/gookit/config/v2/README.md
generated
vendored
@@ -84,7 +84,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/yamlv3"
|
||||
"github.com/gookit/config/v2/yaml"
|
||||
)
|
||||
|
||||
// go run ./examples/yaml.go
|
||||
@@ -92,7 +92,7 @@ func main() {
|
||||
config.WithOptions(config.ParseEnv)
|
||||
|
||||
// add driver for support yaml content
|
||||
config.AddDriver(yamlv3.Driver)
|
||||
config.AddDriver(yaml.Driver)
|
||||
|
||||
err := config.LoadFiles("testdata/yml_base.yml")
|
||||
if err != nil {
|
||||
@@ -389,7 +389,7 @@ Support parse default value by struct tag `default`
|
||||
c := config.New("test").WithOptions(config.ParseDefault)
|
||||
|
||||
// only set name
|
||||
c.SetData(map[string]interface{}{
|
||||
c.SetData(map[string]any{
|
||||
"name": "inhere",
|
||||
})
|
||||
|
||||
@@ -421,7 +421,7 @@ dump.Println(user)
|
||||
### Load Config
|
||||
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` Load data from os ENV
|
||||
- `LoadData(dataSource ...interface{}) (err error)` Load from struts or maps
|
||||
- `LoadData(dataSource ...any) (err error)` Load from struts or maps
|
||||
- `LoadFlags(keys []string) (err error)` Load from CLI flags
|
||||
- `LoadExists(sourceFiles ...string) (err error)`
|
||||
- `LoadFiles(sourceFiles ...string) (err error)`
|
||||
@@ -445,7 +445,7 @@ dump.Println(user)
|
||||
- `Strings(key string) (arr []string)`
|
||||
- `SubDataMap(key string) maputi.Data`
|
||||
- `StringMap(key string) (mp map[string]string)`
|
||||
- `Get(key string, findByPath ...bool) (value interface{})`
|
||||
- `Get(key string, findByPath ...bool) (value any)`
|
||||
|
||||
**Mapping data to struct:**
|
||||
|
||||
@@ -455,14 +455,14 @@ dump.Println(user)
|
||||
|
||||
### Setting Values
|
||||
|
||||
- `Set(key string, val interface{}, setByPath ...bool) (err error)`
|
||||
- `Set(key string, val any, setByPath ...bool) (err error)`
|
||||
|
||||
### Useful Methods
|
||||
|
||||
- `Getenv(name string, defVal ...string) (val string)`
|
||||
- `AddDriver(driver Driver)`
|
||||
- `Data() map[string]interface{}`
|
||||
- `SetData(data map[string]interface{})` set data to override the Config.Data
|
||||
- `Data() map[string]any`
|
||||
- `SetData(data map[string]any)` set data to override the Config.Data
|
||||
- `Exists(key string, findByPath ...bool) bool`
|
||||
- `DumpTo(out io.Writer, format string) (n int64, err error)`
|
||||
|
||||
@@ -497,11 +497,18 @@ Check out these projects, which use https://github.com/gookit/config :
|
||||
|
||||
## See also
|
||||
|
||||
- Ini parse [gookit/ini/parser](https://github.com/gookit/ini/tree/master/parser)
|
||||
- Properties parse [gookit/properties](https://github.com/gookit/properties)
|
||||
- Json5 parse [json5](https://github.com/yosuke-furukawa/json5)
|
||||
- Yaml parse [go-yaml](https://github.com/go-yaml/yaml)
|
||||
- Toml parse [go toml](https://github.com/BurntSushi/toml)
|
||||
- Ini parser [gookit/ini/parser](https://github.com/gookit/ini/tree/master/parser)
|
||||
- Properties parser [gookit/properties](https://github.com/gookit/properties)
|
||||
- Json5 parser
|
||||
- [yosuke-furukawa/json5](https://github.com/yosuke-furukawa/json5)
|
||||
- [titanous/json5](https://github.com/titanous/json5)
|
||||
- Json parser
|
||||
- [goccy/go-json](https://github.com/goccy/go-json)
|
||||
- [json-iterator/go](https://github.com/json-iterator/go)
|
||||
- Yaml parser
|
||||
- [goccy/go-yaml](https://github.com/goccy/go-yaml)
|
||||
- [go-yaml/yaml](https://github.com/go-yaml/yaml)
|
||||
- Toml parser [go toml](https://github.com/BurntSushi/toml)
|
||||
- Data merge [mergo](https://github.com/imdario/mergo)
|
||||
- Map structure [mapstructure](https://github.com/mitchellh/mapstructure)
|
||||
|
||||
|
||||
23
vendor/github.com/gookit/config/v2/README.zh-CN.md
generated
vendored
23
vendor/github.com/gookit/config/v2/README.zh-CN.md
generated
vendored
@@ -83,7 +83,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/yamlv3"
|
||||
"github.com/gookit/config/v2/yaml"
|
||||
)
|
||||
|
||||
// go run ./examples/yaml.go
|
||||
@@ -92,7 +92,7 @@ func main() {
|
||||
config.WithOptions(config.ParseEnv)
|
||||
|
||||
// 添加驱动程序以支持yaml内容解析(除了JSON是默认支持,其他的则是按需使用)
|
||||
config.AddDriver(yamlv3.Driver)
|
||||
config.AddDriver(yaml.Driver)
|
||||
|
||||
// 加载配置,可以同时传入多个文件
|
||||
err := config.LoadFiles("testdata/yml_base.yml")
|
||||
@@ -371,7 +371,7 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
c := config.New("test").WithOptions(config.ParseDefault)
|
||||
|
||||
// only set name
|
||||
c.SetData(map[string]interface{}{
|
||||
c.SetData(map[string]any{
|
||||
"name": "inhere",
|
||||
})
|
||||
|
||||
@@ -402,7 +402,7 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
|
||||
### 载入配置
|
||||
|
||||
- `LoadData(dataSource ...interface{}) (err error)` 从struct或map加载数据
|
||||
- `LoadData(dataSource ...any) (err error)` 从struct或map加载数据
|
||||
- `LoadFlags(keys []string) (err error)` 从命令行参数载入数据
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` 从ENV载入数据
|
||||
- `LoadExists(sourceFiles ...string) (err error)` 从存在的配置文件里加载数据,会忽略不存在的文件
|
||||
@@ -427,25 +427,25 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
- `Strings(key string) (arr []string)`
|
||||
- `StringMap(key string) (mp map[string]string)`
|
||||
- `SubDataMap(key string) maputi.Data`
|
||||
- `Get(key string, findByPath ...bool) (value interface{})`
|
||||
- `Get(key string, findByPath ...bool) (value any)`
|
||||
|
||||
**将数据映射到结构体:**
|
||||
|
||||
- `BindStruct(key string, dst interface{}) error`
|
||||
- `MapOnExists(key string, dst interface{}) error`
|
||||
- `BindStruct(key string, dst any) error`
|
||||
- `MapOnExists(key string, dst any) error`
|
||||
|
||||
### 设置值
|
||||
|
||||
- `Set(key string, val interface{}, setByPath ...bool) (err error)`
|
||||
- `Set(key string, val any, setByPath ...bool) (err error)`
|
||||
|
||||
### 有用的方法
|
||||
|
||||
- `Getenv(name string, defVal ...string) (val string)`
|
||||
- `AddDriver(driver Driver)`
|
||||
- `Data() map[string]interface{}`
|
||||
- `Data() map[string]any`
|
||||
- `Exists(key string, findByPath ...bool) bool`
|
||||
- `DumpTo(out io.Writer, format string) (n int64, err error)`
|
||||
- `SetData(data map[string]interface{})` 设置数据以覆盖 `Config.Data`
|
||||
- `SetData(data map[string]any)` 设置数据以覆盖 `Config.Data`
|
||||
|
||||
## 单元测试
|
||||
|
||||
@@ -484,6 +484,9 @@ go test -cover ./...
|
||||
- Toml 解析 [go toml](https://github.com/BurntSushi/toml)
|
||||
- 数据合并 [mergo](https://github.com/imdario/mergo)
|
||||
- 映射数据到结构体 [mapstructure](https://github.com/mitchellh/mapstructure)
|
||||
- JSON5 解析
|
||||
- [yosuke-furukawa/json5](https://github.com/yosuke-furukawa/json5)
|
||||
- [titanous/json5](https://github.com/titanous/json5)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
6
vendor/github.com/gookit/config/v2/any.go
generated
vendored
6
vendor/github.com/gookit/config/v2/any.go
generated
vendored
@@ -1,6 +0,0 @@
|
||||
package config
|
||||
|
||||
// alias of interface{}
|
||||
//
|
||||
// TIP: cannot add `go:build !go1.18` in file head, that require the go.mod set `go 1.18`
|
||||
type any = interface{}
|
||||
63
vendor/github.com/gookit/config/v2/config.go
generated
vendored
63
vendor/github.com/gookit/config/v2/config.go
generated
vendored
@@ -90,13 +90,15 @@ type Config struct {
|
||||
loadedUrls []string
|
||||
loadedFiles []string
|
||||
driverNames []string
|
||||
reloading bool
|
||||
// driver alias to name map.
|
||||
aliasMap map[string]string
|
||||
reloading bool
|
||||
|
||||
// TODO Deprecated decoder and encoder, use driver instead
|
||||
// drivers map[string]Driver
|
||||
|
||||
// decoders["toml"] = func(blob []byte, v interface{}) (err error){}
|
||||
// decoders["yaml"] = func(blob []byte, v interface{}) (err error){}
|
||||
// decoders["toml"] = func(blob []byte, v any) (err error){}
|
||||
// decoders["yaml"] = func(blob []byte, v any) (err error){}
|
||||
decoders map[string]Decoder
|
||||
encoders map[string]Encoder
|
||||
|
||||
@@ -109,17 +111,9 @@ type Config struct {
|
||||
sMapCache map[string]strMap
|
||||
}
|
||||
|
||||
// New config instance
|
||||
func New(name string) *Config {
|
||||
return &Config{
|
||||
name: name,
|
||||
opts: newDefaultOption(),
|
||||
data: make(map[string]any),
|
||||
|
||||
// default add JSON driver
|
||||
encoders: map[string]Encoder{JSON: JSONEncoder},
|
||||
decoders: map[string]Decoder{JSON: JSONDecoder},
|
||||
}
|
||||
// New config instance, default add JSON driver
|
||||
func New(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name).WithDriver(JSONDriver).WithOptions(opts...)
|
||||
}
|
||||
|
||||
// NewEmpty config instance
|
||||
@@ -132,6 +126,7 @@ func NewEmpty(name string) *Config {
|
||||
// don't add any drivers
|
||||
encoders: map[string]Encoder{},
|
||||
decoders: map[string]Decoder{},
|
||||
aliasMap: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,15 +135,13 @@ func NewWith(name string, fn func(c *Config)) *Config {
|
||||
return New(name).With(fn)
|
||||
}
|
||||
|
||||
// NewWithOptions config instance
|
||||
func NewWithOptions(name string, opts ...func(opts *Options)) *Config {
|
||||
// NewWithOptions config instance. alias of New()
|
||||
func NewWithOptions(name string, opts ...OptionFn) *Config {
|
||||
return New(name).WithOptions(opts...)
|
||||
}
|
||||
|
||||
// Default get the default instance
|
||||
func Default() *Config {
|
||||
return dc
|
||||
}
|
||||
func Default() *Config { return dc }
|
||||
|
||||
/*************************************************************
|
||||
* config drivers
|
||||
@@ -171,6 +164,11 @@ func AddDriver(driver Driver) { dc.AddDriver(driver) }
|
||||
// AddDriver set a decoder and encoder driver for a format.
|
||||
func (c *Config) AddDriver(driver Driver) {
|
||||
format := driver.Name()
|
||||
if len(driver.Aliases()) > 0 {
|
||||
for _, alias := range driver.Aliases() {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
}
|
||||
|
||||
c.driverNames = append(c.driverNames, format)
|
||||
c.decoders[format] = driver.GetDecoder()
|
||||
@@ -179,21 +177,21 @@ func (c *Config) AddDriver(driver Driver) {
|
||||
|
||||
// HasDecoder has decoder
|
||||
func (c *Config) HasDecoder(format string) bool {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.decoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HasEncoder has encoder
|
||||
func (c *Config) HasEncoder(format string) bool {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.encoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// DelDriver delete driver of the format
|
||||
func (c *Config) DelDriver(format string) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
delete(c.decoders, format)
|
||||
delete(c.encoders, format)
|
||||
}
|
||||
@@ -205,6 +203,21 @@ func (c *Config) DelDriver(format string) {
|
||||
// Name get config name
|
||||
func (c *Config) Name() string { return c.name }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
func AddAlias(format, alias string) { dc.AddAlias(format, alias) }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// config.AddAlias("ini", "conf")
|
||||
func (c *Config) AddAlias(format, alias string) {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
|
||||
// AliasMap get alias map
|
||||
func (c *Config) AliasMap() map[string]string { return c.aliasMap }
|
||||
|
||||
// Error get last error, will clear after read.
|
||||
func (c *Config) Error() error {
|
||||
err := c.err
|
||||
@@ -237,8 +250,8 @@ func (c *Config) ClearAll() {
|
||||
c.ClearData()
|
||||
c.ClearCaches()
|
||||
|
||||
c.loadedUrls = []string{}
|
||||
c.loadedFiles = []string{}
|
||||
c.aliasMap = make(map[string]string)
|
||||
// options
|
||||
c.opts.Readonly = false
|
||||
}
|
||||
|
||||
@@ -246,7 +259,7 @@ func (c *Config) ClearAll() {
|
||||
func (c *Config) ClearData() {
|
||||
c.fireHook(OnCleanData)
|
||||
|
||||
c.data = make(map[string]interface{})
|
||||
c.data = make(map[string]any)
|
||||
c.loadedUrls = []string{}
|
||||
c.loadedFiles = []string{}
|
||||
}
|
||||
|
||||
39
vendor/github.com/gookit/config/v2/driver.go
generated
vendored
39
vendor/github.com/gookit/config/v2/driver.go
generated
vendored
@@ -1,6 +1,5 @@
|
||||
package config
|
||||
|
||||
// default json driver(encoder/decoder)
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
@@ -11,10 +10,19 @@ import (
|
||||
// TODO refactor: rename GetDecoder() to Decode(), rename GetEncoder() to Encode()
|
||||
type Driver interface {
|
||||
Name() string
|
||||
Aliases() []string // alias format names, use for resolve format name
|
||||
GetDecoder() Decoder
|
||||
GetEncoder() Encoder
|
||||
}
|
||||
|
||||
// DriverV2 interface.
|
||||
type DriverV2 interface {
|
||||
Name() string // driver name, also is format name.
|
||||
Aliases() []string // alias format names, use for resolve format name
|
||||
Decode(blob []byte, v any) (err error)
|
||||
Encode(v any) (out []byte, err error)
|
||||
}
|
||||
|
||||
// Decoder for decode yml,json,toml format content
|
||||
type Decoder func(blob []byte, v any) (err error)
|
||||
|
||||
@@ -24,6 +32,7 @@ type Encoder func(v any) (out []byte, err error)
|
||||
// StdDriver struct
|
||||
type StdDriver struct {
|
||||
name string
|
||||
aliases []string
|
||||
decoder Decoder
|
||||
encoder Encoder
|
||||
}
|
||||
@@ -33,9 +42,24 @@ func NewDriver(name string, dec Decoder, enc Encoder) *StdDriver {
|
||||
return &StdDriver{name: name, decoder: dec, encoder: enc}
|
||||
}
|
||||
|
||||
// WithAliases set aliases for driver
|
||||
func (d *StdDriver) WithAliases(aliases ...string) *StdDriver {
|
||||
d.aliases = aliases
|
||||
return d
|
||||
}
|
||||
|
||||
// WithAlias add alias for driver
|
||||
func (d *StdDriver) WithAlias(alias string) *StdDriver {
|
||||
d.aliases = append(d.aliases, alias)
|
||||
return d
|
||||
}
|
||||
|
||||
// Name of driver
|
||||
func (d *StdDriver) Name() string {
|
||||
return d.name
|
||||
func (d *StdDriver) Name() string { return d.name }
|
||||
|
||||
// Aliases format name of driver
|
||||
func (d *StdDriver) Aliases() []string {
|
||||
return d.aliases
|
||||
}
|
||||
|
||||
// Decode of driver
|
||||
@@ -59,13 +83,11 @@ func (d *StdDriver) GetEncoder() Encoder {
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* json driver
|
||||
* JSON driver
|
||||
*************************************************************/
|
||||
|
||||
var (
|
||||
// JSONAllowComments support write comments on json file.
|
||||
//
|
||||
// Deprecated: please use JSONDriver.ClearComments = true
|
||||
JSONAllowComments = true
|
||||
|
||||
// JSONMarshalIndent if not empty, will use json.MarshalIndent for encode data.
|
||||
@@ -107,6 +129,11 @@ func (d *jsonDriver) Name() string {
|
||||
return d.driverName
|
||||
}
|
||||
|
||||
// Aliases of the driver
|
||||
func (d *jsonDriver) Aliases() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decode for the driver
|
||||
func (d *jsonDriver) Decode(data []byte, v any) error {
|
||||
if d.ClearComments {
|
||||
|
||||
10
vendor/github.com/gookit/config/v2/export.go
generated
vendored
10
vendor/github.com/gookit/config/v2/export.go
generated
vendored
@@ -55,6 +55,9 @@ func MapOnExists(key string, dst any) error {
|
||||
}
|
||||
|
||||
// MapOnExists mapping data to the dst structure only on key exists.
|
||||
//
|
||||
// - Support ParseEnv on mapping
|
||||
// - Support ParseDefault on mapping
|
||||
func (c *Config) MapOnExists(key string, dst any) error {
|
||||
err := c.Structure(key, dst)
|
||||
if err != nil && err == ErrNotFound {
|
||||
@@ -66,12 +69,15 @@ func (c *Config) MapOnExists(key string, dst any) error {
|
||||
|
||||
// Structure get config data and binding to the dst structure.
|
||||
//
|
||||
// - Support ParseEnv on mapping
|
||||
// - Support ParseDefault on mapping
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// dbInfo := Db{}
|
||||
// config.Structure("db", &dbInfo)
|
||||
func (c *Config) Structure(key string, dst any) error {
|
||||
var data interface{}
|
||||
var data any
|
||||
// binding all data
|
||||
if key == "" {
|
||||
data = c.data
|
||||
@@ -133,7 +139,7 @@ func (c *Config) DumpTo(out io.Writer, format string) (n int64, err error) {
|
||||
var ok bool
|
||||
var encoder Encoder
|
||||
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
if encoder, ok = c.encoders[format]; !ok {
|
||||
err = errors.New("not exists/register encoder for the format: " + format)
|
||||
return
|
||||
|
||||
37
vendor/github.com/gookit/config/v2/load.go
generated
vendored
37
vendor/github.com/gookit/config/v2/load.go
generated
vendored
@@ -4,13 +4,15 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/goutil/errorx"
|
||||
"github.com/gookit/goutil/fsutil"
|
||||
"github.com/imdario/mergo"
|
||||
)
|
||||
@@ -42,6 +44,10 @@ func LoadExists(sourceFiles ...string) error { return dc.LoadExists(sourceFiles.
|
||||
// LoadExists load and parse config files, but will ignore not exists file.
|
||||
func (c *Config) LoadExists(sourceFiles ...string) (err error) {
|
||||
for _, file := range sourceFiles {
|
||||
if file == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = c.loadFile(file, true, ""); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -72,7 +78,7 @@ func (c *Config) LoadRemote(format, url string) (err error) {
|
||||
}
|
||||
|
||||
// read response content
|
||||
bts, err := ioutil.ReadAll(resp.Body)
|
||||
bts, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
if err = c.parseSourceCode(format, bts); err != nil {
|
||||
return
|
||||
@@ -191,15 +197,21 @@ func LoadData(dataSource ...any) error { return dc.LoadData(dataSource...) }
|
||||
//
|
||||
// The dataSources can be:
|
||||
// - map[string]any
|
||||
// - map[string]string
|
||||
func (c *Config) LoadData(dataSources ...any) (err error) {
|
||||
if c.opts.Delimiter == 0 {
|
||||
c.opts.Delimiter = defaultDelimiter
|
||||
}
|
||||
|
||||
for _, ds := range dataSources {
|
||||
if smp, ok := ds.(map[string]string); ok {
|
||||
c.LoadSMap(smp)
|
||||
continue
|
||||
}
|
||||
|
||||
err = mergo.Merge(&c.data, ds, mergo.WithOverride)
|
||||
if err != nil {
|
||||
return
|
||||
return errorx.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +219,14 @@ func (c *Config) LoadData(dataSources ...any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// LoadSMap to config
|
||||
func (c *Config) LoadSMap(smp map[string]string) {
|
||||
for k, v := range smp {
|
||||
c.data[k] = v
|
||||
}
|
||||
c.fireHook(OnLoadData)
|
||||
}
|
||||
|
||||
// LoadSources load one or multi byte data
|
||||
func LoadSources(format string, src []byte, more ...[]byte) error {
|
||||
return dc.LoadSources(format, src, more...)
|
||||
@@ -314,9 +334,8 @@ func (c *Config) LoadFromDir(dirPath, format string) (err error) {
|
||||
extName := "." + format
|
||||
extLen := len(extName)
|
||||
|
||||
return fsutil.FindInDir(dirPath, func(fPath string, fi os.FileInfo) error {
|
||||
baseName := fi.Name()
|
||||
|
||||
return fsutil.FindInDir(dirPath, func(fPath string, ent fs.DirEntry) error {
|
||||
baseName := ent.Name()
|
||||
if strings.HasSuffix(baseName, extName) {
|
||||
data, err := c.parseSourceToMap(format, fsutil.MustReadFile(fPath))
|
||||
if err != nil {
|
||||
@@ -386,7 +405,7 @@ func (c *Config) loadFile(file string, loadExist bool, format string) (err error
|
||||
defer fd.Close()
|
||||
|
||||
// read file content
|
||||
bts, err := ioutil.ReadAll(fd)
|
||||
bts, err := io.ReadAll(fd)
|
||||
if err == nil {
|
||||
// get format for file ext
|
||||
if format == "" {
|
||||
@@ -431,8 +450,8 @@ func (c *Config) loadDataMap(data map[string]any) (err error) {
|
||||
}
|
||||
|
||||
// parse config source code to Config.
|
||||
func (c *Config) parseSourceToMap(format string, blob []byte) (map[string]interface{}, error) {
|
||||
format = fixFormat(format)
|
||||
func (c *Config) parseSourceToMap(format string, blob []byte) (map[string]any, error) {
|
||||
format = c.resolveFormat(format)
|
||||
decode := c.decoders[format]
|
||||
if decode == nil {
|
||||
return nil, errors.New("not register decoder for the format: " + format)
|
||||
|
||||
7
vendor/github.com/gookit/config/v2/options.go
generated
vendored
7
vendor/github.com/gookit/config/v2/options.go
generated
vendored
@@ -50,6 +50,9 @@ type Options struct {
|
||||
// WatchChange bool
|
||||
}
|
||||
|
||||
// OptionFn option func
|
||||
type OptionFn func(*Options)
|
||||
|
||||
func newDefaultOption() *Options {
|
||||
return &Options{
|
||||
ParseKey: true,
|
||||
@@ -159,10 +162,10 @@ func WithHookFunc(fn HookFunc) func(*Options) {
|
||||
func EnableCache(opts *Options) { opts.EnableCache = true }
|
||||
|
||||
// WithOptions with options
|
||||
func WithOptions(opts ...func(*Options)) { dc.WithOptions(opts...) }
|
||||
func WithOptions(opts ...OptionFn) { dc.WithOptions(opts...) }
|
||||
|
||||
// WithOptions apply some options
|
||||
func (c *Config) WithOptions(opts ...func(opts *Options)) *Config {
|
||||
func (c *Config) WithOptions(opts ...OptionFn) *Config {
|
||||
if !c.IsEmpty() {
|
||||
panic("config: Cannot set options after data has been loaded")
|
||||
}
|
||||
|
||||
58
vendor/github.com/gookit/config/v2/read.go
generated
vendored
58
vendor/github.com/gookit/config/v2/read.go
generated
vendored
@@ -90,32 +90,46 @@ func (c *Config) Exists(key string, findByPath ...bool) (ok bool) {
|
||||
*************************************************************/
|
||||
|
||||
// Data return all config data
|
||||
func Data() map[string]interface{} { return dc.Data() }
|
||||
func Data() map[string]any { return dc.Data() }
|
||||
|
||||
// Data get all config data
|
||||
func (c *Config) Data() map[string]interface{} {
|
||||
// Data get all config data.
|
||||
//
|
||||
// Note: will don't apply any options, like ParseEnv
|
||||
func (c *Config) Data() map[string]any {
|
||||
return c.data
|
||||
}
|
||||
|
||||
// Keys return all config data
|
||||
func Keys() []string { return dc.Keys() }
|
||||
|
||||
// Keys get all config data
|
||||
func (c *Config) Keys() []string {
|
||||
keys := make([]string, 0, len(c.data))
|
||||
for key := range c.data {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Get config value by key string, support get sub-value by key path(eg. 'map.key'),
|
||||
//
|
||||
// - ok is true, find value from config
|
||||
// - ok is false, not found or error
|
||||
func Get(key string, findByPath ...bool) interface{} { return dc.Get(key, findByPath...) }
|
||||
func Get(key string, findByPath ...bool) any { return dc.Get(key, findByPath...) }
|
||||
|
||||
// Get config value by key
|
||||
func (c *Config) Get(key string, findByPath ...bool) interface{} {
|
||||
func (c *Config) Get(key string, findByPath ...bool) any {
|
||||
val, _ := c.GetValue(key, findByPath...)
|
||||
return val
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
func GetValue(key string, findByPath ...bool) (interface{}, bool) {
|
||||
func GetValue(key string, findByPath ...bool) (any, bool) {
|
||||
return dc.GetValue(key, findByPath...)
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
func (c *Config) GetValue(key string, findByPath ...bool) (value interface{}, ok bool) {
|
||||
func (c *Config) GetValue(key string, findByPath ...bool) (value any, ok bool) {
|
||||
sep := c.opts.Delimiter
|
||||
if key = formatKey(key, string(sep)); key == "" {
|
||||
c.addError(ErrKeyIsEmpty)
|
||||
@@ -235,6 +249,18 @@ func (c *Config) String(key string, defVal ...string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// MustString get a string by key, will panic on empty or not exists
|
||||
func MustString(key string) string { return dc.MustString(key) }
|
||||
|
||||
// MustString get a string by key, will panic on empty or not exists
|
||||
func (c *Config) MustString(key string) string {
|
||||
value, ok := c.getString(key)
|
||||
if !ok {
|
||||
panic("config: string value not found, key: " + key)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (c *Config) getString(key string) (value string, ok bool) {
|
||||
// find from cache
|
||||
if c.opts.EnableCache && len(c.strCache) > 0 {
|
||||
@@ -257,8 +283,11 @@ func (c *Config) getString(key string) (value string, ok bool) {
|
||||
value = envutil.ParseEnvValue(value)
|
||||
}
|
||||
default:
|
||||
// value = fmt.Sprintf("%v", val)
|
||||
value, _ = strutil.AnyToString(val, false)
|
||||
var err error
|
||||
value, err = strutil.AnyToString(val, false)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
// add cache
|
||||
@@ -520,6 +549,17 @@ func (c *Config) Strings(key string) (arr []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// StringsBySplit get []string by split a string value.
|
||||
func StringsBySplit(key, sep string) []string { return dc.StringsBySplit(key, sep) }
|
||||
|
||||
// StringsBySplit get []string by split a string value.
|
||||
func (c *Config) StringsBySplit(key, sep string) (ss []string) {
|
||||
if str, ok := c.getString(key); ok {
|
||||
ss = strutil.Split(str, sep)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StringMap get config data as a map[string]string
|
||||
func StringMap(key string) map[string]string { return dc.StringMap(key) }
|
||||
|
||||
|
||||
37
vendor/github.com/gookit/config/v2/util.go
generated
vendored
37
vendor/github.com/gookit/config/v2/util.go
generated
vendored
@@ -13,12 +13,15 @@ import (
|
||||
// ValDecodeHookFunc returns a mapstructure.DecodeHookFunc
|
||||
// that parse ENV var, and more custom parse
|
||||
func ValDecodeHookFunc(parseEnv, parseTime bool) mapstructure.DecodeHookFunc {
|
||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
||||
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||
if f.Kind() != reflect.String {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
str := data.(string)
|
||||
if parseEnv {
|
||||
str = envutil.ParseEnvValue(str)
|
||||
}
|
||||
if len(str) < 2 {
|
||||
return str, nil
|
||||
}
|
||||
@@ -32,14 +35,19 @@ func ValDecodeHookFunc(parseEnv, parseTime bool) mapstructure.DecodeHookFunc {
|
||||
return dur, nil
|
||||
}
|
||||
}
|
||||
} else if parseEnv { // parse ENV value
|
||||
str = envutil.ParseEnvValue(str)
|
||||
}
|
||||
|
||||
return str, nil
|
||||
}
|
||||
}
|
||||
|
||||
// resolve format, check is alias
|
||||
func (c *Config) resolveFormat(f string) string {
|
||||
if name, ok := c.aliasMap[f]; ok {
|
||||
return name
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Deprecated methods
|
||||
*************************************************************/
|
||||
@@ -55,7 +63,7 @@ func SetDecoder(format string, decoder Decoder) {
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetDecoder(format string, decoder Decoder) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
c.decoders[format] = decoder
|
||||
}
|
||||
|
||||
@@ -79,7 +87,7 @@ func SetEncoder(format string, encoder Encoder) {
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetEncoder(format string, encoder Encoder) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
c.encoders[format] = encoder
|
||||
}
|
||||
|
||||
@@ -141,20 +149,3 @@ func parseVarNameAndType(key string) (string, string) {
|
||||
func formatKey(key, sep string) string {
|
||||
return strings.Trim(strings.TrimSpace(key), sep)
|
||||
}
|
||||
|
||||
// resolve fix inc/conf/yaml format
|
||||
func fixFormat(f string) string {
|
||||
if f == Yml {
|
||||
f = Yaml
|
||||
}
|
||||
|
||||
if f == "inc" {
|
||||
f = Ini
|
||||
}
|
||||
|
||||
// eg nginx config file.
|
||||
if f == "conf" {
|
||||
f = Hcl
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
6
vendor/github.com/gookit/config/v2/yaml/yaml.go
generated
vendored
6
vendor/github.com/gookit/config/v2/yaml/yaml.go
generated
vendored
@@ -5,10 +5,9 @@ Usage please see example:
|
||||
*/
|
||||
package yaml
|
||||
|
||||
// see https://pkg.go.dev/gopkg.in/yaml.v2
|
||||
import (
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/gookit/config/v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Decoder the yaml content decoder
|
||||
@@ -18,5 +17,4 @@ var Decoder config.Decoder = yaml.Unmarshal
|
||||
var Encoder config.Encoder = yaml.Marshal
|
||||
|
||||
// Driver for yaml
|
||||
// TIP: recommended use the yamlv3.Driver
|
||||
var Driver = config.NewDriver(config.Yaml, Decoder, Encoder)
|
||||
var Driver = config.NewDriver(config.Yaml, Decoder, Encoder).WithAliases(config.Yml)
|
||||
|
||||
2
vendor/github.com/gookit/goutil/Makefile
generated
vendored
2
vendor/github.com/gookit/goutil/Makefile
generated
vendored
@@ -29,7 +29,7 @@ readme:
|
||||
readme-c: ## Generate or update README file and commit change to git
|
||||
readme-c: readme
|
||||
git add README.* internal
|
||||
git commit -m "doc: update and re-generate README docs"
|
||||
git commit -m ":memo: doc: update and re-generate README docs"
|
||||
|
||||
csfix: ## Fix code style for all files by go fmt
|
||||
csfix:
|
||||
|
||||
1625
vendor/github.com/gookit/goutil/README.md
generated
vendored
1625
vendor/github.com/gookit/goutil/README.md
generated
vendored
File diff suppressed because it is too large
Load Diff
1625
vendor/github.com/gookit/goutil/README.zh-CN.md
generated
vendored
1625
vendor/github.com/gookit/goutil/README.zh-CN.md
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/github.com/gookit/goutil/arrutil/README.md
generated
vendored
2
vendor/github.com/gookit/goutil/arrutil/README.md
generated
vendored
@@ -12,6 +12,8 @@ go get github.com/gookit/goutil/arrutil
|
||||
|
||||
## Functions API
|
||||
|
||||
> **Note**: doc by run `go doc ./arrutil`
|
||||
|
||||
```go
|
||||
func AnyToString(arr any) string
|
||||
func CloneSlice(data any) interface{}
|
||||
|
||||
22
vendor/github.com/gookit/goutil/arrutil/arrutil.go
generated
vendored
22
vendor/github.com/gookit/goutil/arrutil/arrutil.go
generated
vendored
@@ -104,11 +104,15 @@ func RandomOne[T any](arr []T) T {
|
||||
}
|
||||
|
||||
// Unique value in the given slice data.
|
||||
func Unique[T ~string | comdef.XintOrFloat](arr []T) []T {
|
||||
valMap := make(map[T]struct{}, len(arr))
|
||||
uniArr := make([]T, 0, len(arr))
|
||||
func Unique[T ~string | comdef.XintOrFloat](list []T) []T {
|
||||
if len(list) < 2 {
|
||||
return list
|
||||
}
|
||||
|
||||
for _, t := range arr {
|
||||
valMap := make(map[T]struct{}, len(list))
|
||||
uniArr := make([]T, 0, len(list))
|
||||
|
||||
for _, t := range list {
|
||||
if _, ok := valMap[t]; !ok {
|
||||
valMap[t] = struct{}{}
|
||||
uniArr = append(uniArr, t)
|
||||
@@ -116,3 +120,13 @@ func Unique[T ~string | comdef.XintOrFloat](arr []T) []T {
|
||||
}
|
||||
return uniArr
|
||||
}
|
||||
|
||||
// IndexOf value in given slice.
|
||||
func IndexOf[T ~string | comdef.XintOrFloat](val T, list []T) int {
|
||||
for i, v := range list {
|
||||
if v == val {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
45
vendor/github.com/gookit/goutil/arrutil/check.go
generated
vendored
45
vendor/github.com/gookit/goutil/arrutil/check.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/mathutil"
|
||||
)
|
||||
|
||||
@@ -40,12 +41,48 @@ func StringsHas(ss []string, val string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// HasValue check array(strings, intXs, uintXs) should be contained the given value(int(X),string).
|
||||
func HasValue(arr, val any) bool {
|
||||
return Contains(arr, val)
|
||||
// NotIn check the given value whether not in the list
|
||||
func NotIn[T comdef.ScalarType](value T, list []T) bool {
|
||||
return !In(value, list)
|
||||
}
|
||||
|
||||
// Contains check array(strings, intXs, uintXs) should be contained the given value(int(X),string).
|
||||
// In check the given value whether in the list
|
||||
func In[T comdef.ScalarType](value T, list []T) bool {
|
||||
for _, elem := range list {
|
||||
if elem == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsAll check given values is sub-list of sample list.
|
||||
func ContainsAll[T comdef.ScalarType](list, values []T) bool {
|
||||
return IsSubList(values, list)
|
||||
}
|
||||
|
||||
// IsSubList check given values is sub-list of sample list.
|
||||
func IsSubList[T comdef.ScalarType](values, list []T) bool {
|
||||
for _, value := range values {
|
||||
if !In(value, list) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsParent check given values is parent-list of samples.
|
||||
func IsParent[T comdef.ScalarType](values, list []T) bool {
|
||||
return IsSubList(list, values)
|
||||
}
|
||||
|
||||
// HasValue check array(strings, intXs, uintXs) should be contained the given value(int(X),string).
|
||||
func HasValue(arr, val any) bool { return Contains(arr, val) }
|
||||
|
||||
// Contains check slice/array(strings, intXs, uintXs) should be contained the given value(int(X),string).
|
||||
//
|
||||
// TIP: Difference the In(), Contains() will try to convert value type,
|
||||
// and Contains() support array type.
|
||||
func Contains(arr, val any) bool {
|
||||
if val == nil || arr == nil {
|
||||
return false
|
||||
|
||||
52
vendor/github.com/gookit/goutil/arrutil/collection.go
generated
vendored
52
vendor/github.com/gookit/goutil/arrutil/collection.go
generated
vendored
@@ -160,6 +160,58 @@ func CloneSlice(data any) any {
|
||||
return reflect.AppendSlice(reflect.New(reflect.SliceOf(typeOfData.Elem())).Elem(), reflect.ValueOf(data)).Interface()
|
||||
}
|
||||
|
||||
// Differences Produces the set difference of two slice according to a comparer function.
|
||||
//
|
||||
// first: the first slice. MUST BE A SLICE.
|
||||
// second: the second slice. MUST BE A SLICE.
|
||||
// fn: the comparer function.
|
||||
// returns: the difference of the two slices.
|
||||
func Differences[T any](first, second []T, fn Comparer) []T {
|
||||
typeOfFirst := reflect.TypeOf(first)
|
||||
if typeOfFirst.Kind() != reflect.Slice {
|
||||
panic("collections.Excepts: first must be a slice")
|
||||
}
|
||||
|
||||
typeOfSecond := reflect.TypeOf(second)
|
||||
if typeOfSecond.Kind() != reflect.Slice {
|
||||
panic("collections.Excepts: second must be a slice")
|
||||
}
|
||||
|
||||
firstLen := len(first)
|
||||
if firstLen == 0 {
|
||||
return CloneSlice(second).([]T)
|
||||
}
|
||||
|
||||
secondLen := len(second)
|
||||
if secondLen == 0 {
|
||||
return CloneSlice(first).([]T)
|
||||
}
|
||||
|
||||
max := firstLen
|
||||
if secondLen > firstLen {
|
||||
max = secondLen
|
||||
}
|
||||
|
||||
result := make([]T, 0)
|
||||
for i := 0; i < max; i++ {
|
||||
if i < firstLen {
|
||||
s := first[i]
|
||||
if i, _ := TwowaySearch(second, s, fn); i < 0 {
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
|
||||
if i < secondLen {
|
||||
t := second[i]
|
||||
if i, _ := TwowaySearch(first, t, fn); i < 0 {
|
||||
result = append(result, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Excepts Produces the set difference of two slice according to a comparer function.
|
||||
//
|
||||
// first: the first slice. MUST BE A SLICE.
|
||||
|
||||
6
vendor/github.com/gookit/goutil/arrutil/collection_gte118.go
generated
vendored
6
vendor/github.com/gookit/goutil/arrutil/collection_gte118.go
generated
vendored
@@ -2,12 +2,14 @@ package arrutil
|
||||
|
||||
// type MapFn func(obj T) (target V, find bool)
|
||||
|
||||
// Map an object list [object0{},object1{},...] to flatten list [object0.someKey, object1.someKey, ...]
|
||||
// Map a list to new list
|
||||
//
|
||||
// eg: mapping [object0{},object1{},...] to flatten list [object0.someKey, object1.someKey, ...]
|
||||
func Map[T any, V any](list []T, mapFn func(obj T) (val V, find bool)) []V {
|
||||
flatArr := make([]V, 0, len(list))
|
||||
|
||||
for _, obj := range list {
|
||||
if target, find := mapFn(obj); find {
|
||||
if target, ok := mapFn(obj); ok {
|
||||
flatArr = append(flatArr, target)
|
||||
}
|
||||
}
|
||||
|
||||
182
vendor/github.com/gookit/goutil/arrutil/convert.go
generated
vendored
182
vendor/github.com/gookit/goutil/arrutil/convert.go
generated
vendored
@@ -6,7 +6,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/mathutil"
|
||||
"github.com/gookit/goutil/reflects"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
@@ -14,7 +16,7 @@ import (
|
||||
var ErrInvalidType = errors.New("the input param type is invalid")
|
||||
|
||||
/*************************************************************
|
||||
* helper func for strings
|
||||
* Join func for slice
|
||||
*************************************************************/
|
||||
|
||||
// JoinStrings alias of strings.Join
|
||||
@@ -27,32 +29,21 @@ func StringsJoin(sep string, ss ...string) string {
|
||||
return strings.Join(ss, sep)
|
||||
}
|
||||
|
||||
// StringsToInts string slice to int slice
|
||||
func StringsToInts(ss []string) (ints []int, err error) {
|
||||
for _, str := range ss {
|
||||
iVal, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// JoinSlice join []any slice to string.
|
||||
func JoinSlice(sep string, arr ...any) string {
|
||||
if arr == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(sep)
|
||||
}
|
||||
|
||||
ints = append(ints, iVal)
|
||||
sb.WriteString(strutil.QuietString(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MustToStrings convert array or slice to []string
|
||||
func MustToStrings(arr any) []string {
|
||||
ret, _ := ToStrings(arr)
|
||||
return ret
|
||||
}
|
||||
|
||||
// StringsToSlice convert []string to []any
|
||||
func StringsToSlice(ss []string) []any {
|
||||
args := make([]any, len(ss))
|
||||
for i, s := range ss {
|
||||
args[i] = s
|
||||
}
|
||||
return args
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
@@ -88,14 +79,79 @@ func MustToInt64s(arr any) []int64 {
|
||||
func SliceToInt64s(arr []any) []int64 {
|
||||
i64s := make([]int64, len(arr))
|
||||
for i, v := range arr {
|
||||
i64s[i] = mathutil.MustInt64(v)
|
||||
i64s[i] = mathutil.QuietInt64(v)
|
||||
}
|
||||
return i64s
|
||||
}
|
||||
|
||||
// StringsAsInts convert and ignore error
|
||||
func StringsAsInts(ss []string) []int {
|
||||
ints, _ := StringsTryInts(ss)
|
||||
return ints
|
||||
}
|
||||
|
||||
// StringsToInts string slice to int slice
|
||||
func StringsToInts(ss []string) (ints []int, err error) {
|
||||
return StringsTryInts(ss)
|
||||
}
|
||||
|
||||
// StringsTryInts string slice to int slice
|
||||
func StringsTryInts(ss []string) (ints []int, err error) {
|
||||
for _, str := range ss {
|
||||
iVal, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ints = append(ints, iVal)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AnyToSlice convert any(allow: array,slice) to []any
|
||||
func AnyToSlice(sl any) (ls []any, err error) {
|
||||
rfKeys := reflect.ValueOf(sl)
|
||||
if rfKeys.Kind() != reflect.Slice && rfKeys.Kind() != reflect.Array {
|
||||
return nil, ErrInvalidType
|
||||
}
|
||||
|
||||
for i := 0; i < rfKeys.Len(); i++ {
|
||||
ls = append(ls, rfKeys.Index(i).Interface())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AnyToStrings convert array or slice to []string
|
||||
func AnyToStrings(arr any) []string {
|
||||
ret, _ := ToStrings(arr)
|
||||
return ret
|
||||
}
|
||||
|
||||
// MustToStrings convert array or slice to []string
|
||||
func MustToStrings(arr any) []string {
|
||||
ret, err := ToStrings(arr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// StringsToSlice convert []string to []any
|
||||
func StringsToSlice(ss []string) []any {
|
||||
args := make([]any, len(ss))
|
||||
for i, s := range ss {
|
||||
args[i] = s
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// ToStrings convert any(allow: array,slice) to []string
|
||||
func ToStrings(arr any) (ret []string, err error) {
|
||||
rv := reflect.ValueOf(arr)
|
||||
if rv.Kind() == reflect.String {
|
||||
return []string{rv.String()}, nil
|
||||
}
|
||||
|
||||
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
|
||||
err = ErrInvalidType
|
||||
return
|
||||
@@ -114,13 +170,47 @@ func ToStrings(arr any) (ret []string, err error) {
|
||||
|
||||
// SliceToStrings convert []any to []string
|
||||
func SliceToStrings(arr []any) []string {
|
||||
return QuietStrings(arr)
|
||||
}
|
||||
|
||||
// QuietStrings convert []any to []string
|
||||
func QuietStrings(arr []any) []string {
|
||||
ss := make([]string, len(arr))
|
||||
for i, v := range arr {
|
||||
ss[i] = strutil.MustString(v)
|
||||
ss[i] = strutil.QuietString(v)
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
// ConvType convert type of slice elements to new type slice, by the given newElemTyp type.
|
||||
//
|
||||
// Supports conversion between []string, []intX, []uintX, []floatX.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// ints, _ := arrutil.ConvType([]string{"12", "23"}, 1) // []int{12, 23}
|
||||
func ConvType[T any, R any](arr []T, newElemTyp R) ([]R, error) {
|
||||
newArr := make([]R, len(arr))
|
||||
elemTyp := reflect.TypeOf(newElemTyp)
|
||||
|
||||
for i, elem := range arr {
|
||||
var anyElem any = elem
|
||||
// type is same.
|
||||
if _, ok := anyElem.(R); ok {
|
||||
newArr[i] = anyElem.(R)
|
||||
continue
|
||||
}
|
||||
|
||||
// need conv type.
|
||||
rfVal, err := reflects.ValueByType(elem, elemTyp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newArr[i] = rfVal.Interface().(R)
|
||||
}
|
||||
return newArr, nil
|
||||
}
|
||||
|
||||
// AnyToString simple and quickly convert any array, slice to string
|
||||
func AnyToString(arr any) string {
|
||||
return NewFormatter(arr).Format()
|
||||
@@ -143,26 +233,40 @@ func ToString(arr []any) string {
|
||||
if i > 0 {
|
||||
sb.WriteByte(',')
|
||||
}
|
||||
sb.WriteString(strutil.MustString(v))
|
||||
sb.WriteString(strutil.QuietString(v))
|
||||
}
|
||||
|
||||
sb.WriteByte(']')
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// JoinSlice join []any slice to string.
|
||||
func JoinSlice(sep string, arr ...any) string {
|
||||
if arr == nil {
|
||||
return ""
|
||||
}
|
||||
// CombineToMap combine two slice to map[K]V.
|
||||
//
|
||||
// If keys length is greater than values, the extra keys will be ignored.
|
||||
func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V {
|
||||
ln := len(values)
|
||||
mp := make(map[K]V, len(keys))
|
||||
|
||||
var sb strings.Builder
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(sep)
|
||||
for i, key := range keys {
|
||||
if i >= ln {
|
||||
break
|
||||
}
|
||||
sb.WriteString(strutil.MustString(v))
|
||||
mp[key] = values[i]
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
return mp
|
||||
}
|
||||
|
||||
// CombineToSMap combine two string-slice to map[string]string
|
||||
func CombineToSMap(keys, values []string) map[string]string {
|
||||
ln := len(values)
|
||||
mp := make(map[string]string, len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
if ln > i {
|
||||
mp[key] = values[i]
|
||||
} else {
|
||||
mp[key] = ""
|
||||
}
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
13
vendor/github.com/gookit/goutil/arrutil/enum.go
generated
vendored
13
vendor/github.com/gookit/goutil/arrutil/enum.go
generated
vendored
@@ -42,6 +42,11 @@ func (ss Strings) Join(sep string) string {
|
||||
|
||||
// Has given element
|
||||
func (ss Strings) Has(sub string) bool {
|
||||
return ss.Contains(sub)
|
||||
}
|
||||
|
||||
// Contains given element
|
||||
func (ss Strings) Contains(sub string) bool {
|
||||
for _, s := range ss {
|
||||
if s == sub {
|
||||
return true
|
||||
@@ -49,3 +54,11 @@ func (ss Strings) Has(sub string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// First element value.
|
||||
func (ss Strings) First() string {
|
||||
if len(ss) > 0 {
|
||||
return ss[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
80
vendor/github.com/gookit/goutil/basefn/basefunc.go
generated
vendored
Normal file
80
vendor/github.com/gookit/goutil/basefn/basefunc.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Package basefn provide some no-dependents util functions
|
||||
package basefn
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Panicf format panic message use fmt.Sprintf
|
||||
func Panicf(format string, v ...any) {
|
||||
panic(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// MustOK if error is not empty, will panic
|
||||
func MustOK(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Must if error is not empty, will panic
|
||||
func Must[T any](v T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// ErrOnFail return input error on cond is false, otherwise return nil
|
||||
func ErrOnFail(cond bool, err error) error {
|
||||
return OrError(cond, err)
|
||||
}
|
||||
|
||||
// OrError return input error on cond is false, otherwise return nil
|
||||
func OrError(cond bool, err error) error {
|
||||
if !cond {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FirstOr get first elem or elseVal
|
||||
func FirstOr[T any](sl []T, elseVal T) T {
|
||||
if len(sl) > 0 {
|
||||
return sl[0]
|
||||
}
|
||||
return elseVal
|
||||
}
|
||||
|
||||
// OrValue get
|
||||
func OrValue[T any](cond bool, okVal, elVal T) T {
|
||||
if cond {
|
||||
return okVal
|
||||
}
|
||||
return elVal
|
||||
}
|
||||
|
||||
// OrReturn call okFunc() on condition is true, else call elseFn()
|
||||
func OrReturn[T any](cond bool, okFn, elseFn func() T) T {
|
||||
if cond {
|
||||
return okFn()
|
||||
}
|
||||
return elseFn()
|
||||
}
|
||||
|
||||
// ErrFunc type
|
||||
type ErrFunc func() error
|
||||
|
||||
// CallOn call func on condition is true
|
||||
func CallOn(cond bool, fn ErrFunc) error {
|
||||
if cond {
|
||||
return fn()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CallOrElse call okFunc() on condition is true, else call elseFn()
|
||||
func CallOrElse(cond bool, okFn, elseFn ErrFunc) error {
|
||||
if cond {
|
||||
return okFn()
|
||||
}
|
||||
return elseFn()
|
||||
}
|
||||
@@ -1,6 +1,28 @@
|
||||
package fmtutil
|
||||
package basefn
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DataSize format bytes number friendly. eg: 1024 => 1KB, 1024*1024 => 1MB
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// file, err := os.Open(path)
|
||||
// fl, err := file.Stat()
|
||||
// fmtSize := DataSize(fl.Size())
|
||||
func DataSize(size uint64) string {
|
||||
switch {
|
||||
case size < 1024:
|
||||
return fmt.Sprintf("%dB", size)
|
||||
case size < 1024*1024:
|
||||
return fmt.Sprintf("%.2fK", float64(size)/1024)
|
||||
case size < 1024*1024*1024:
|
||||
return fmt.Sprintf("%.2fM", float64(size)/1024/1024)
|
||||
default:
|
||||
return fmt.Sprintf("%.2fG", float64(size)/1024/1024/1024)
|
||||
}
|
||||
}
|
||||
|
||||
var timeFormats = [][]int{
|
||||
{0},
|
||||
55
vendor/github.com/gookit/goutil/byteutil/README.md
generated
vendored
Normal file
55
vendor/github.com/gookit/goutil/byteutil/README.md
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# Bytes Util
|
||||
|
||||
Provide some commonly bytes util functions.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
go get github.com/gookit/goutil/byteutil
|
||||
```
|
||||
|
||||
## Go docs
|
||||
|
||||
- [Go docs](https://pkg.go.dev/github.com/gookit/goutil/byteutil)
|
||||
|
||||
## Functions API
|
||||
|
||||
> **Note**: doc by run `go doc ./byteutil`
|
||||
|
||||
```go
|
||||
func AppendAny(dst []byte, v any) []byte
|
||||
func FirstLine(bs []byte) []byte
|
||||
func IsNumChar(c byte) bool
|
||||
func Md5(src any) []byte
|
||||
func Random(length int) ([]byte, error)
|
||||
func SafeString(bs []byte, err error) string
|
||||
func StrOrErr(bs []byte, err error) (string, error)
|
||||
func String(b []byte) string
|
||||
func ToString(b []byte) string
|
||||
type Buffer struct{ ... }
|
||||
func NewBuffer() *Buffer
|
||||
type BytesEncoder interface{ ... }
|
||||
type ChanPool struct{ ... }
|
||||
func NewChanPool(maxSize int, width int, capWidth int) *ChanPool
|
||||
type StdEncoder struct{ ... }
|
||||
func NewStdEncoder(encFn func(src []byte) []byte, decFn func(src []byte) ([]byte, error)) *StdEncoder
|
||||
```
|
||||
|
||||
## Code Check & Testing
|
||||
|
||||
```bash
|
||||
gofmt -w -l ./
|
||||
golint ./...
|
||||
```
|
||||
|
||||
**Testing**:
|
||||
|
||||
```shell
|
||||
go test -v ./byteutil/...
|
||||
```
|
||||
|
||||
**Test limit by regexp**:
|
||||
|
||||
```shell
|
||||
go test -v -run ^TestSetByKeys ./byteutil/...
|
||||
```
|
||||
65
vendor/github.com/gookit/goutil/byteutil/buffer.go
generated
vendored
Normal file
65
vendor/github.com/gookit/goutil/byteutil/buffer.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package byteutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Buffer wrap and extends the bytes.Buffer
|
||||
type Buffer struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
// NewBuffer instance
|
||||
func NewBuffer() *Buffer {
|
||||
return &Buffer{}
|
||||
}
|
||||
|
||||
// WriteAny type value to buffer
|
||||
func (b *Buffer) WriteAny(vs ...any) {
|
||||
for _, v := range vs {
|
||||
_, _ = b.Buffer.WriteString(fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
|
||||
// QuietWriteByte to buffer
|
||||
func (b *Buffer) QuietWriteByte(c byte) {
|
||||
_ = b.WriteByte(c)
|
||||
}
|
||||
|
||||
// QuietWritef write message to buffer
|
||||
func (b *Buffer) QuietWritef(tpl string, vs ...any) {
|
||||
_, _ = b.WriteString(fmt.Sprintf(tpl, vs...))
|
||||
}
|
||||
|
||||
// Writeln write message to buffer with newline
|
||||
func (b *Buffer) Writeln(ss ...string) {
|
||||
b.QuietWriteln(ss...)
|
||||
}
|
||||
|
||||
// QuietWriteln write message to buffer with newline
|
||||
func (b *Buffer) QuietWriteln(ss ...string) {
|
||||
_, _ = b.WriteString(strings.Join(ss, ""))
|
||||
_ = b.WriteByte('\n')
|
||||
}
|
||||
|
||||
// QuietWriteString to buffer
|
||||
func (b *Buffer) QuietWriteString(ss ...string) {
|
||||
_, _ = b.WriteString(strings.Join(ss, ""))
|
||||
}
|
||||
|
||||
// MustWriteString to buffer
|
||||
func (b *Buffer) MustWriteString(ss ...string) {
|
||||
_, err := b.WriteString(strings.Join(ss, ""))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ResetAndGet buffer string.
|
||||
func (b *Buffer) ResetAndGet() string {
|
||||
s := b.String()
|
||||
b.Reset()
|
||||
return s
|
||||
}
|
||||
115
vendor/github.com/gookit/goutil/byteutil/byteutil.go
generated
vendored
Normal file
115
vendor/github.com/gookit/goutil/byteutil/byteutil.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package byteutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Random bytes generate
|
||||
func Random(length int) ([]byte, error) {
|
||||
b := make([]byte, length)
|
||||
// Note that err == nil only if we read len(b) bytes.
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// FirstLine from command output
|
||||
func FirstLine(bs []byte) []byte {
|
||||
if i := bytes.IndexByte(bs, '\n'); i >= 0 {
|
||||
return bs[0:i]
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
// StrOrErr convert to string, return empty string on error.
|
||||
func StrOrErr(bs []byte, err error) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// SafeString convert to string, return empty string on error.
|
||||
func SafeString(bs []byte, err error) string {
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
// String unsafe convert bytes to string
|
||||
func String(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// ToString convert bytes to string
|
||||
func ToString(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// AppendAny append any value to byte slice
|
||||
func AppendAny(dst []byte, v any) []byte {
|
||||
if v == nil {
|
||||
return append(dst, "<nil>"...)
|
||||
}
|
||||
|
||||
switch val := v.(type) {
|
||||
case []byte:
|
||||
dst = append(dst, val...)
|
||||
case string:
|
||||
dst = append(dst, val...)
|
||||
case int:
|
||||
dst = strconv.AppendInt(dst, int64(val), 10)
|
||||
case int8:
|
||||
dst = strconv.AppendInt(dst, int64(val), 10)
|
||||
case int16:
|
||||
dst = strconv.AppendInt(dst, int64(val), 10)
|
||||
case int32:
|
||||
dst = strconv.AppendInt(dst, int64(val), 10)
|
||||
case int64:
|
||||
dst = strconv.AppendInt(dst, val, 10)
|
||||
case uint:
|
||||
dst = strconv.AppendUint(dst, uint64(val), 10)
|
||||
case uint8:
|
||||
dst = strconv.AppendUint(dst, uint64(val), 10)
|
||||
case uint16:
|
||||
dst = strconv.AppendUint(dst, uint64(val), 10)
|
||||
case uint32:
|
||||
dst = strconv.AppendUint(dst, uint64(val), 10)
|
||||
case uint64:
|
||||
dst = strconv.AppendUint(dst, val, 10)
|
||||
case float32:
|
||||
dst = strconv.AppendFloat(dst, float64(val), 'f', -1, 32)
|
||||
case float64:
|
||||
dst = strconv.AppendFloat(dst, val, 'f', -1, 64)
|
||||
case bool:
|
||||
dst = strconv.AppendBool(dst, val)
|
||||
case time.Time:
|
||||
dst = val.AppendFormat(dst, time.RFC3339)
|
||||
case time.Duration:
|
||||
dst = strconv.AppendInt(dst, int64(val), 10)
|
||||
case error:
|
||||
dst = append(dst, val.Error()...)
|
||||
case fmt.Stringer:
|
||||
dst = append(dst, val.String()...)
|
||||
default:
|
||||
dst = append(dst, fmt.Sprint(v)...)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Cut bytes. like the strings.Cut()
|
||||
func Cut(bs []byte, sep byte) (before, after []byte, found bool) {
|
||||
if i := bytes.IndexByte(bs, sep); i >= 0 {
|
||||
return bs[:i], bs[i+1:], true
|
||||
}
|
||||
|
||||
before = bs
|
||||
return
|
||||
}
|
||||
19
vendor/github.com/gookit/goutil/byteutil/bytex.go
generated
vendored
Normal file
19
vendor/github.com/gookit/goutil/byteutil/bytex.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// Package byteutil Provide some bytes utils functions or structs
|
||||
package byteutil
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Md5 Generate a 32-bit md5 bytes
|
||||
func Md5(src any) []byte {
|
||||
h := md5.New()
|
||||
|
||||
if s, ok := src.(string); ok {
|
||||
h.Write([]byte(s))
|
||||
} else {
|
||||
h.Write([]byte(fmt.Sprint(src)))
|
||||
}
|
||||
return h.Sum(nil)
|
||||
}
|
||||
4
vendor/github.com/gookit/goutil/byteutil/check.go
generated
vendored
Normal file
4
vendor/github.com/gookit/goutil/byteutil/check.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
package byteutil
|
||||
|
||||
// IsNumChar returns true if the given character is a numeric, otherwise false.
|
||||
func IsNumChar(c byte) bool { return c >= '0' && c <= '9' }
|
||||
63
vendor/github.com/gookit/goutil/byteutil/encoder.go
generated
vendored
Normal file
63
vendor/github.com/gookit/goutil/byteutil/encoder.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package byteutil
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// BytesEncoder interface
|
||||
type BytesEncoder interface {
|
||||
Encode(src []byte) []byte
|
||||
Decode(src []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// StdEncoder implement the BytesEncoder
|
||||
type StdEncoder struct {
|
||||
encodeFn func(src []byte) []byte
|
||||
decodeFn func(src []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// NewStdEncoder instance
|
||||
func NewStdEncoder(encFn func(src []byte) []byte, decFn func(src []byte) ([]byte, error)) *StdEncoder {
|
||||
return &StdEncoder{
|
||||
encodeFn: encFn,
|
||||
decodeFn: decFn,
|
||||
}
|
||||
}
|
||||
|
||||
// Encode input
|
||||
func (e *StdEncoder) Encode(src []byte) []byte {
|
||||
return e.encodeFn(src)
|
||||
}
|
||||
|
||||
// Decode input
|
||||
func (e *StdEncoder) Decode(src []byte) ([]byte, error) {
|
||||
return e.decodeFn(src)
|
||||
}
|
||||
|
||||
var (
|
||||
// HexEncoder instance
|
||||
HexEncoder = NewStdEncoder(func(src []byte) []byte {
|
||||
dst := make([]byte, hex.EncodedLen(len(src)))
|
||||
hex.Encode(dst, src)
|
||||
return dst
|
||||
}, func(src []byte) ([]byte, error) {
|
||||
n, err := hex.Decode(src, src)
|
||||
return src[:n], err
|
||||
})
|
||||
|
||||
// B64Encoder instance
|
||||
B64Encoder = NewStdEncoder(func(src []byte) []byte {
|
||||
b64Dst := make([]byte, base64.StdEncoding.EncodedLen(len(src)))
|
||||
base64.StdEncoding.Encode(b64Dst, src)
|
||||
return b64Dst
|
||||
}, func(src []byte) ([]byte, error) {
|
||||
dBuf := make([]byte, base64.StdEncoding.DecodedLen(len(src)))
|
||||
n, err := base64.StdEncoding.Decode(dBuf, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dBuf[:n], err
|
||||
})
|
||||
)
|
||||
64
vendor/github.com/gookit/goutil/byteutil/pool.go
generated
vendored
Normal file
64
vendor/github.com/gookit/goutil/byteutil/pool.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package byteutil
|
||||
|
||||
// ChanPool struct
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// bp := strutil.NewByteChanPool(500, 1024, 1024)
|
||||
// buf:=bp.Get()
|
||||
// defer bp.Put(buf)
|
||||
// // use buf do something ...
|
||||
//
|
||||
// refer https://www.flysnow.org/2020/08/21/golang-chan-byte-pool.html
|
||||
// from https://github.com/minio/minio/blob/master/internal/bpool/bpool.go
|
||||
type ChanPool struct {
|
||||
c chan []byte
|
||||
w int
|
||||
wcap int
|
||||
}
|
||||
|
||||
// NewChanPool instance
|
||||
func NewChanPool(maxSize int, width int, capWidth int) *ChanPool {
|
||||
return &ChanPool{
|
||||
c: make(chan []byte, maxSize),
|
||||
w: width,
|
||||
wcap: capWidth,
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets a []byte from the BytePool, or creates a new one if none are
|
||||
// available in the pool.
|
||||
func (bp *ChanPool) Get() (b []byte) {
|
||||
select {
|
||||
case b = <-bp.c:
|
||||
// reuse existing buffer
|
||||
default:
|
||||
// create new buffer
|
||||
if bp.wcap > 0 {
|
||||
b = make([]byte, bp.w, bp.wcap)
|
||||
} else {
|
||||
b = make([]byte, bp.w)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Put returns the given Buffer to the BytePool.
|
||||
func (bp *ChanPool) Put(b []byte) {
|
||||
select {
|
||||
case bp.c <- b:
|
||||
// buffer went back into pool
|
||||
default:
|
||||
// buffer didn't go back into pool, just discard
|
||||
}
|
||||
}
|
||||
|
||||
// Width returns the width of the byte arrays in this pool.
|
||||
func (bp *ChanPool) Width() (n int) {
|
||||
return bp.w
|
||||
}
|
||||
|
||||
// WidthCap returns the cap width of the byte arrays in this pool.
|
||||
func (bp *ChanPool) WidthCap() (n int) {
|
||||
return bp.wcap
|
||||
}
|
||||
78
vendor/github.com/gookit/goutil/cliutil/cmdline/builder.go
generated
vendored
78
vendor/github.com/gookit/goutil/cliutil/cmdline/builder.go
generated
vendored
@@ -2,27 +2,28 @@ package cmdline
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// LineBuilder build command line string.
|
||||
// codes refer from strings.Builder
|
||||
type LineBuilder struct {
|
||||
buf []byte
|
||||
strings.Builder
|
||||
}
|
||||
|
||||
// NewBuilder create
|
||||
func NewBuilder(binFile string, args ...string) *LineBuilder {
|
||||
b := &LineBuilder{}
|
||||
b.AddArg(binFile)
|
||||
|
||||
if binFile != "" {
|
||||
b.AddArg(binFile)
|
||||
}
|
||||
|
||||
b.AddArray(args)
|
||||
return b
|
||||
}
|
||||
|
||||
// LineBuild build command line string by given args.
|
||||
func LineBuild(binFile string, args []string) string {
|
||||
return NewBuilder(binFile, args...).String()
|
||||
}
|
||||
|
||||
// AddArg to builder
|
||||
func (b *LineBuilder) AddArg(arg string) {
|
||||
_, _ = b.WriteString(arg)
|
||||
@@ -40,52 +41,45 @@ func (b *LineBuilder) AddArray(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// AddAny args to builder
|
||||
func (b *LineBuilder) AddAny(args ...any) {
|
||||
for _, arg := range args {
|
||||
_, _ = b.WriteString(strutil.SafeString(arg))
|
||||
}
|
||||
}
|
||||
|
||||
// WriteString arg string to the builder, will auto quote special string.
|
||||
// refer strconv.Quote()
|
||||
func (b *LineBuilder) WriteString(a string) (int, error) {
|
||||
var quote byte
|
||||
if strings.ContainsRune(a, '"') {
|
||||
if pos := strings.IndexByte(a, '"'); pos > -1 {
|
||||
quote = '\''
|
||||
} else if a == "" || strings.ContainsRune(a, '\'') || strings.ContainsRune(a, ' ') {
|
||||
// fix: a = `--pretty=format:"one two three"`
|
||||
if pos > 0 && '"' == a[len(a)-1] {
|
||||
quote = 0
|
||||
}
|
||||
} else if pos := strings.IndexByte(a, '\''); pos > -1 {
|
||||
quote = '"'
|
||||
// fix: a = "--pretty=format:'one two three'"
|
||||
if pos > 0 && '\'' == a[len(a)-1] {
|
||||
quote = 0
|
||||
}
|
||||
} else if a == "" || strings.ContainsRune(a, ' ') {
|
||||
quote = '"'
|
||||
}
|
||||
|
||||
// add sep on first write.
|
||||
if b.buf != nil {
|
||||
b.buf = append(b.buf, ' ')
|
||||
// add sep on not-first write.
|
||||
if b.Len() != 0 {
|
||||
_ = b.WriteByte(' ')
|
||||
}
|
||||
|
||||
// no quote char
|
||||
// no quote char OR not need quote
|
||||
if quote == 0 {
|
||||
b.buf = append(b.buf, a...)
|
||||
return len(a) + 1, nil
|
||||
return b.Builder.WriteString(a)
|
||||
}
|
||||
|
||||
b.buf = append(b.buf, quote) // add start quote
|
||||
b.buf = append(b.buf, a...)
|
||||
b.buf = append(b.buf, quote) // add end quote
|
||||
return len(a) + 3, nil
|
||||
_ = b.WriteByte(quote) // add start quote
|
||||
n, err := b.Builder.WriteString(a)
|
||||
_ = b.WriteByte(quote) // add end quote
|
||||
return n, err
|
||||
}
|
||||
|
||||
// String to command line string
|
||||
func (b *LineBuilder) String() string {
|
||||
return string(b.buf)
|
||||
}
|
||||
|
||||
// Len of the builder
|
||||
func (b *LineBuilder) Len() int {
|
||||
return len(b.buf)
|
||||
}
|
||||
|
||||
// Reset builder
|
||||
func (b *LineBuilder) Reset() {
|
||||
b.buf = nil
|
||||
}
|
||||
|
||||
// grow copies the buffer to a new, larger buffer so that there are at least n
|
||||
// bytes of capacity beyond len(b.buf).
|
||||
// func (b *LineBuilder) grow(n int) {
|
||||
// buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)
|
||||
// copy(buf, b.buf)
|
||||
// b.buf = buf
|
||||
// }
|
||||
|
||||
10
vendor/github.com/gookit/goutil/cliutil/cmdline/cmdline.go
generated
vendored
10
vendor/github.com/gookit/goutil/cliutil/cmdline/cmdline.go
generated
vendored
@@ -1,2 +1,12 @@
|
||||
// Package cmdline provide quick build and parse cmd line string.
|
||||
package cmdline
|
||||
|
||||
// LineBuild build command line string by given args.
|
||||
func LineBuild(binFile string, args []string) string {
|
||||
return NewBuilder(binFile, args...).String()
|
||||
}
|
||||
|
||||
// ParseLine input command line text. alias of the StringToOSArgs()
|
||||
func ParseLine(line string) []string {
|
||||
return NewParser(line).Parse()
|
||||
}
|
||||
|
||||
215
vendor/github.com/gookit/goutil/cliutil/cmdline/parser.go
generated
vendored
215
vendor/github.com/gookit/goutil/cliutil/cmdline/parser.go
generated
vendored
@@ -1,9 +1,13 @@
|
||||
package cmdline
|
||||
|
||||
import (
|
||||
"os"
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// LineParser struct
|
||||
@@ -11,7 +15,7 @@ import (
|
||||
type LineParser struct {
|
||||
parsed bool
|
||||
// Line the full input command line text
|
||||
// eg `kite top sub -a "the a message" --foo val1 --bar "val 2"`
|
||||
// eg `kite top sub -a "this is a message" --foo val1 --bar "val 2"`
|
||||
Line string
|
||||
// ParseEnv parse ENV var on the line.
|
||||
ParseEnv bool
|
||||
@@ -19,6 +23,11 @@ type LineParser struct {
|
||||
nodes []string
|
||||
// the parsed args
|
||||
args []string
|
||||
|
||||
// temp value
|
||||
quoteChar byte
|
||||
quoteIndex int // if > 0, mark is not on start
|
||||
tempNode bytes.Buffer
|
||||
}
|
||||
|
||||
// NewParser create
|
||||
@@ -26,11 +35,10 @@ func NewParser(line string) *LineParser {
|
||||
return &LineParser{Line: line}
|
||||
}
|
||||
|
||||
// ParseLine input command line text. alias of the StringToOSArgs()
|
||||
func ParseLine(line string) []string {
|
||||
p := &LineParser{Line: line}
|
||||
|
||||
return p.Parse()
|
||||
// WithParseEnv with parse ENV var
|
||||
func (p *LineParser) WithParseEnv() *LineParser {
|
||||
p.ParseEnv = true
|
||||
return p
|
||||
}
|
||||
|
||||
// AlsoEnvParse input command line text to os.Args, will parse ENV var
|
||||
@@ -39,90 +47,13 @@ func (p *LineParser) AlsoEnvParse() []string {
|
||||
return p.Parse()
|
||||
}
|
||||
|
||||
// Parse input command line text to os.Args
|
||||
func (p *LineParser) Parse() []string {
|
||||
if p.parsed {
|
||||
return p.args
|
||||
}
|
||||
// NewExecCmd quick create exec.Cmd by cmdline string
|
||||
func (p *LineParser) NewExecCmd() *exec.Cmd {
|
||||
// parse get bin and args
|
||||
binName, args := p.BinAndArgs()
|
||||
|
||||
p.parsed = true
|
||||
p.Line = strings.TrimSpace(p.Line)
|
||||
if p.Line == "" {
|
||||
return p.args
|
||||
}
|
||||
|
||||
// enable parse Env var
|
||||
if p.ParseEnv {
|
||||
p.Line = os.ExpandEnv(p.Line)
|
||||
}
|
||||
|
||||
p.nodes = strings.Split(p.Line, " ")
|
||||
if len(p.nodes) == 1 {
|
||||
p.args = p.nodes
|
||||
return p.args
|
||||
}
|
||||
|
||||
// temp value
|
||||
var quoteChar, fullNode string
|
||||
for _, node := range p.nodes {
|
||||
if node == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
nodeLen := len(node)
|
||||
start, end := node[:1], node[nodeLen-1:]
|
||||
|
||||
var clearTemp bool
|
||||
if start == "'" || start == `"` {
|
||||
noStart := node[1:]
|
||||
if quoteChar == "" { // start
|
||||
// only one words. eg: `-m "msg"`
|
||||
if end == start {
|
||||
p.args = append(p.args, node[1:nodeLen-1])
|
||||
continue
|
||||
}
|
||||
|
||||
fullNode += noStart
|
||||
quoteChar = start
|
||||
} else if quoteChar == start { // invalid. eg: `-m "this is "message` `-m "this is "message"`
|
||||
p.appendWithPrefix(strings.Trim(node, quoteChar), fullNode)
|
||||
clearTemp = true // clear temp value
|
||||
} else if quoteChar == end { // eg: `"has inner 'quote'"`
|
||||
p.appendWithPrefix(node[:nodeLen-1], fullNode)
|
||||
clearTemp = true // clear temp value
|
||||
} else { // goon. eg: `-m "the 'some' message"`
|
||||
fullNode += " " + node
|
||||
}
|
||||
} else if end == "'" || end == `"` {
|
||||
noEnd := node[:nodeLen-1]
|
||||
if quoteChar == "" { // end
|
||||
p.appendWithPrefix(noEnd, fullNode)
|
||||
clearTemp = true // clear temp value
|
||||
} else if quoteChar == end { // end
|
||||
p.appendWithPrefix(noEnd, fullNode)
|
||||
clearTemp = true // clear temp value
|
||||
} else { // goon. eg: `-m "the 'some' message"`
|
||||
fullNode += " " + node
|
||||
}
|
||||
} else {
|
||||
if quoteChar != "" {
|
||||
fullNode += " " + node
|
||||
} else {
|
||||
p.args = append(p.args, node)
|
||||
}
|
||||
}
|
||||
|
||||
// clear temp value
|
||||
if clearTemp {
|
||||
quoteChar, fullNode = "", ""
|
||||
}
|
||||
}
|
||||
|
||||
if fullNode != "" {
|
||||
p.args = append(p.args, fullNode)
|
||||
}
|
||||
|
||||
return p.args
|
||||
// create a new Cmd instance
|
||||
return exec.Command(binName, args...)
|
||||
}
|
||||
|
||||
// BinAndArgs get binName and args
|
||||
@@ -141,19 +72,103 @@ func (p *LineParser) BinAndArgs() (bin string, args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewExecCmd quick create exec.Cmd by cmdline string
|
||||
func (p *LineParser) NewExecCmd() *exec.Cmd {
|
||||
// parse get bin and args
|
||||
binName, args := p.BinAndArgs()
|
||||
// Parse input command line text to os.Args
|
||||
func (p *LineParser) Parse() []string {
|
||||
if p.parsed {
|
||||
return p.args
|
||||
}
|
||||
|
||||
// create a new Cmd instance
|
||||
return exec.Command(binName, args...)
|
||||
p.parsed = true
|
||||
p.Line = strings.TrimSpace(p.Line)
|
||||
if p.Line == "" {
|
||||
return p.args
|
||||
}
|
||||
|
||||
// enable parse Env var
|
||||
if p.ParseEnv {
|
||||
p.Line = comfunc.ParseEnvVar(p.Line, nil)
|
||||
}
|
||||
|
||||
p.nodes = strings.Split(p.Line, " ")
|
||||
if len(p.nodes) == 1 {
|
||||
p.args = p.nodes
|
||||
return p.args
|
||||
}
|
||||
|
||||
for i := 0; i < len(p.nodes); i++ {
|
||||
node := p.nodes[i]
|
||||
if node == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
p.parseNode(node)
|
||||
}
|
||||
|
||||
p.nodes = p.nodes[:0]
|
||||
if p.tempNode.Len() > 0 {
|
||||
p.appendTempNode()
|
||||
}
|
||||
return p.args
|
||||
}
|
||||
|
||||
func (p *LineParser) appendWithPrefix(node, prefix string) {
|
||||
if prefix != "" {
|
||||
p.args = append(p.args, prefix+" "+node)
|
||||
func (p *LineParser) parseNode(node string) {
|
||||
maxIdx := len(node) - 1
|
||||
start, end := node[0], node[maxIdx]
|
||||
|
||||
// in quotes
|
||||
if p.quoteChar != 0 {
|
||||
p.tempNode.WriteByte(' ')
|
||||
|
||||
// end quotes
|
||||
if end == p.quoteChar {
|
||||
if p.quoteIndex > 0 {
|
||||
p.tempNode.WriteString(node) // eg: node="--pretty=format:'one two'"
|
||||
} else {
|
||||
p.tempNode.WriteString(node[:maxIdx]) // remove last quote
|
||||
}
|
||||
p.appendTempNode()
|
||||
} else { // goon ... write to temp node
|
||||
p.tempNode.WriteString(node)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// quote start
|
||||
if start == comdef.DoubleQuote || start == comdef.SingleQuote {
|
||||
// only one words. eg: `-m "msg"`
|
||||
if end == start {
|
||||
p.args = append(p.args, node[1:maxIdx])
|
||||
return
|
||||
}
|
||||
|
||||
p.quoteChar = start
|
||||
p.tempNode.WriteString(node[1:])
|
||||
} else if end == comdef.DoubleQuote || end == comdef.SingleQuote {
|
||||
p.args = append(p.args, node) // only one node: `msg"`
|
||||
} else {
|
||||
p.args = append(p.args, node)
|
||||
// eg: --pretty=format:'one two three'
|
||||
if strutil.ContainsByte(node, comdef.DoubleQuote) {
|
||||
p.quoteIndex = 1 // mark is not on start
|
||||
p.quoteChar = comdef.DoubleQuote
|
||||
} else if strutil.ContainsByte(node, comdef.SingleQuote) {
|
||||
p.quoteIndex = 1
|
||||
p.quoteChar = comdef.SingleQuote
|
||||
}
|
||||
|
||||
// in quote, append to temp-node
|
||||
if p.quoteChar != 0 {
|
||||
p.tempNode.WriteString(node)
|
||||
} else {
|
||||
p.args = append(p.args, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *LineParser) appendTempNode() {
|
||||
p.args = append(p.args, p.tempNode.String())
|
||||
|
||||
// reset context value
|
||||
p.quoteChar = 0
|
||||
p.quoteIndex = 0
|
||||
p.tempNode.Reset()
|
||||
}
|
||||
|
||||
2
vendor/github.com/gookit/goutil/comdef/consts.go
generated
vendored
2
vendor/github.com/gookit/goutil/comdef/consts.go
generated
vendored
@@ -23,3 +23,5 @@ const (
|
||||
|
||||
// NoIdx invalid index or length
|
||||
const NoIdx = -1
|
||||
|
||||
// const VarPathReg = `(\w[\w-]*(?:\.[\w-]+)*)`
|
||||
|
||||
13
vendor/github.com/gookit/goutil/comdef/types.go
generated
vendored
13
vendor/github.com/gookit/goutil/comdef/types.go
generated
vendored
@@ -7,12 +7,11 @@ type Int interface {
|
||||
|
||||
// Uint interface type
|
||||
type Uint interface {
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||
}
|
||||
|
||||
// Xint interface type. all int or uint types
|
||||
type Xint interface {
|
||||
// equal: ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint32 | ~uint64
|
||||
Int | Uint
|
||||
}
|
||||
|
||||
@@ -26,11 +25,19 @@ type IntOrFloat interface {
|
||||
Int | Float
|
||||
}
|
||||
|
||||
// XintOrFloat interface type. all (x)int and float types
|
||||
// XintOrFloat interface type. all int, uint and float types
|
||||
type XintOrFloat interface {
|
||||
Int | Uint | Float
|
||||
}
|
||||
|
||||
// SortedType interface type.
|
||||
// that supports the operators < <= >= >.
|
||||
//
|
||||
// contains: (x)int, float, ~string types
|
||||
type SortedType interface {
|
||||
Int | Uint | Float | ~string
|
||||
}
|
||||
|
||||
// ScalarType interface type.
|
||||
//
|
||||
// contains: (x)int, float, ~string, ~bool types
|
||||
|
||||
2
vendor/github.com/gookit/goutil/envutil/README.md
generated
vendored
2
vendor/github.com/gookit/goutil/envutil/README.md
generated
vendored
@@ -14,6 +14,8 @@ go get github.com/gookit/goutil/envutil
|
||||
|
||||
## Functions API
|
||||
|
||||
> **Note**: doc by run `go doc ./envutil`
|
||||
|
||||
```go
|
||||
func Environ() map[string]string
|
||||
func GetBool(name string, def ...bool) bool
|
||||
|
||||
23
vendor/github.com/gookit/goutil/envutil/envutil.go
generated
vendored
23
vendor/github.com/gookit/goutil/envutil/envutil.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
// Package envutil provide some commonly ENV util functions.
|
||||
package envutil
|
||||
|
||||
import (
|
||||
@@ -41,9 +42,27 @@ func ParseValue(val string) (newVal string) {
|
||||
return comfunc.ParseEnvVar(val, ValueGetter)
|
||||
}
|
||||
|
||||
// SetEnvs to os
|
||||
func SetEnvs(mp map[string]string) {
|
||||
// SetEnvMap set multi ENV(string-map) to os
|
||||
func SetEnvMap(mp map[string]string) {
|
||||
for key, value := range mp {
|
||||
_ = os.Setenv(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// SetEnvs set multi k-v ENV pairs to os
|
||||
func SetEnvs(kvPairs ...string) {
|
||||
if len(kvPairs)%2 == 1 {
|
||||
panic("envutil.SetEnvs: odd argument count")
|
||||
}
|
||||
|
||||
for i := 0; i < len(kvPairs); i += 2 {
|
||||
_ = os.Setenv(kvPairs[i], kvPairs[i+1])
|
||||
}
|
||||
}
|
||||
|
||||
// UnsetEnvs from os
|
||||
func UnsetEnvs(keys ...string) {
|
||||
for _, key := range keys {
|
||||
_ = os.Unsetenv(key)
|
||||
}
|
||||
}
|
||||
|
||||
45
vendor/github.com/gookit/goutil/envutil/get.go
generated
vendored
45
vendor/github.com/gookit/goutil/envutil/get.go
generated
vendored
@@ -2,6 +2,7 @@ package envutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
@@ -40,7 +41,45 @@ func GetBool(name string, def ...bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Environ like os.Environ, but will returns key-value map[string]string data.
|
||||
func Environ() map[string]string {
|
||||
return comfunc.Environ()
|
||||
// GetMulti ENV values by input names.
|
||||
func GetMulti(names ...string) map[string]string {
|
||||
valMap := make(map[string]string, len(names))
|
||||
|
||||
for _, name := range names {
|
||||
if val := os.Getenv(name); val != "" {
|
||||
valMap[name] = val
|
||||
}
|
||||
}
|
||||
return valMap
|
||||
}
|
||||
|
||||
// EnvPaths get and split $PATH to []string
|
||||
func EnvPaths() []string {
|
||||
return filepath.SplitList(os.Getenv("PATH"))
|
||||
}
|
||||
|
||||
// EnvMap like os.Environ, but will returns key-value map[string]string data.
|
||||
func EnvMap() map[string]string { return comfunc.Environ() }
|
||||
|
||||
// Environ like os.Environ, but will returns key-value map[string]string data.
|
||||
func Environ() map[string]string { return comfunc.Environ() }
|
||||
|
||||
// SearchEnvKeys values by given keywords
|
||||
func SearchEnvKeys(keywords string) map[string]string {
|
||||
return SearchEnv(keywords, false)
|
||||
}
|
||||
|
||||
// SearchEnv values by given keywords
|
||||
func SearchEnv(keywords string, matchValue bool) map[string]string {
|
||||
founded := make(map[string]string)
|
||||
|
||||
for name, val := range comfunc.Environ() {
|
||||
if strutil.IContains(name, keywords) {
|
||||
founded[name] = val
|
||||
} else if matchValue && strutil.IContains(val, keywords) {
|
||||
founded[name] = val
|
||||
}
|
||||
}
|
||||
|
||||
return founded
|
||||
}
|
||||
|
||||
61
vendor/github.com/gookit/goutil/errorx/assert.go
generated
vendored
Normal file
61
vendor/github.com/gookit/goutil/errorx/assert.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
package errorx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gookit/goutil/arrutil"
|
||||
"github.com/gookit/goutil/comdef"
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// IsTrue assert result is true, otherwise will return error
|
||||
func IsTrue(result bool, fmtAndArgs ...any) error {
|
||||
if !result {
|
||||
return errors.New(formatErrMsg("result should be True", fmtAndArgs))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsFalse assert result is false, otherwise will return error
|
||||
func IsFalse(result bool, fmtAndArgs ...any) error {
|
||||
if result {
|
||||
return errors.New(formatErrMsg("result should be False", fmtAndArgs))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsIn value should be in the list, otherwise will return error
|
||||
func IsIn[T comdef.ScalarType](value T, list []T, fmtAndArgs ...any) error {
|
||||
if arrutil.NotIn(value, list) {
|
||||
var errMsg string
|
||||
if len(fmtAndArgs) > 0 {
|
||||
errMsg = comfunc.FormatTplAndArgs(fmtAndArgs)
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("value should be in the %v", list)
|
||||
}
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotIn value should not be in the list, otherwise will return error
|
||||
func NotIn[T comdef.ScalarType](value T, list []T, fmtAndArgs ...any) error {
|
||||
if arrutil.In(value, list) {
|
||||
var errMsg string
|
||||
if len(fmtAndArgs) > 0 {
|
||||
errMsg = comfunc.FormatTplAndArgs(fmtAndArgs)
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("value should not be in the %v", list)
|
||||
}
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatErrMsg(errMsg string, fmtAndArgs []any) string {
|
||||
if len(fmtAndArgs) > 0 {
|
||||
errMsg = comfunc.FormatTplAndArgs(fmtAndArgs)
|
||||
}
|
||||
return errMsg
|
||||
}
|
||||
7
vendor/github.com/gookit/goutil/errorx/errors.go
generated
vendored
7
vendor/github.com/gookit/goutil/errorx/errors.go
generated
vendored
@@ -37,6 +37,11 @@ func Fail(code int, msg string) ErrorR {
|
||||
return &errorR{code: code, msg: msg}
|
||||
}
|
||||
|
||||
// Failf code with error response
|
||||
func Failf(code int, tpl string, v ...any) ErrorR {
|
||||
return &errorR{code: code, msg: fmt.Sprintf(tpl, v...)}
|
||||
}
|
||||
|
||||
// Suc success response reply
|
||||
func Suc(msg string) ErrorR {
|
||||
return &errorR{code: 0, msg: msg}
|
||||
@@ -110,6 +115,8 @@ func (e ErrMap) One() error {
|
||||
|
||||
// Errors multi error list
|
||||
type Errors []error
|
||||
|
||||
// ErrList alias for Errors
|
||||
type ErrList = Errors
|
||||
|
||||
// Error string
|
||||
|
||||
22
vendor/github.com/gookit/goutil/errorx/util.go
generated
vendored
22
vendor/github.com/gookit/goutil/errorx/util.go
generated
vendored
@@ -5,11 +5,31 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// E new a raw go error. alias of errors.New()
|
||||
func E(msg string) error {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
// Err new a raw go error. alias of errors.New()
|
||||
func Err(msg string) error {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
// Raw new a raw go error. alias of errors.New()
|
||||
func Raw(msg string) error {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
// Ef new a raw go error. alias of errors.New()
|
||||
func Ef(tpl string, vars ...any) error {
|
||||
return fmt.Errorf(tpl, vars...)
|
||||
}
|
||||
|
||||
// Errf new a raw go error. alias of errors.New()
|
||||
func Errf(tpl string, vars ...any) error {
|
||||
return fmt.Errorf(tpl, vars...)
|
||||
}
|
||||
|
||||
// Rawf new a raw go error. alias of errors.New()
|
||||
func Rawf(tpl string, vars ...any) error {
|
||||
return fmt.Errorf(tpl, vars...)
|
||||
@@ -54,7 +74,7 @@ func ToErrorX(err error) (ex *ErrorX, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// Has check err has contains target, or err is eq target.
|
||||
// Has contains target error, or err is eq target.
|
||||
// alias of errors.Is()
|
||||
func Has(err, target error) bool {
|
||||
return errors.Is(err, target)
|
||||
|
||||
2
vendor/github.com/gookit/goutil/fmtutil/fmtutil.go
generated
vendored
2
vendor/github.com/gookit/goutil/fmtutil/fmtutil.go
generated
vendored
@@ -1,2 +0,0 @@
|
||||
// Package fmtutil provide some format util functions.
|
||||
package fmtutil
|
||||
116
vendor/github.com/gookit/goutil/fmtutil/format.go
generated
vendored
116
vendor/github.com/gookit/goutil/fmtutil/format.go
generated
vendored
@@ -1,116 +0,0 @@
|
||||
package fmtutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// data size
|
||||
const (
|
||||
OneKByte = 1024
|
||||
OneMByte = 1024 * 1024
|
||||
OneGByte = 1024 * 1024
|
||||
)
|
||||
|
||||
// DataSize format bytes number friendly.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// file, err := os.Open(path)
|
||||
// fl, err := file.Stat()
|
||||
// fmtSize := DataSize(fl.Size())
|
||||
func DataSize(size uint64) string {
|
||||
switch {
|
||||
case size < 1024:
|
||||
return fmt.Sprintf("%dB", size)
|
||||
case size < 1024*1024:
|
||||
return fmt.Sprintf("%.2fK", float64(size)/1024)
|
||||
case size < 1024*1024*1024:
|
||||
return fmt.Sprintf("%.2fM", float64(size)/1024/1024)
|
||||
default:
|
||||
return fmt.Sprintf("%.2fG", float64(size)/1024/1024/1024)
|
||||
}
|
||||
}
|
||||
|
||||
// SizeToString alias of the DataSize
|
||||
func SizeToString(size uint64) string { return DataSize(size) }
|
||||
|
||||
// StringToByte alias of the ParseByte
|
||||
func StringToByte(sizeStr string) uint64 { return ParseByte(sizeStr) }
|
||||
|
||||
// ParseByte converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes
|
||||
func ParseByte(sizeStr string) uint64 {
|
||||
sizeStr = strings.TrimSpace(sizeStr)
|
||||
lastPos := len(sizeStr) - 1
|
||||
if lastPos < 1 {
|
||||
return 0
|
||||
}
|
||||
|
||||
if sizeStr[lastPos] == 'b' || sizeStr[lastPos] == 'B' {
|
||||
// last second char is k,m,g
|
||||
lastSec := sizeStr[lastPos-1]
|
||||
if lastSec > 'A' {
|
||||
lastPos -= 1
|
||||
}
|
||||
}
|
||||
|
||||
multiplier := float64(1)
|
||||
switch unicode.ToLower(rune(sizeStr[lastPos])) {
|
||||
case 'k':
|
||||
multiplier = 1 << 10
|
||||
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
|
||||
case 'm':
|
||||
multiplier = 1 << 20
|
||||
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
|
||||
case 'g':
|
||||
multiplier = 1 << 30
|
||||
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
|
||||
default: // b
|
||||
multiplier = 1
|
||||
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
|
||||
}
|
||||
|
||||
size, _ := strconv.ParseFloat(sizeStr, 64)
|
||||
if size < 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return uint64(size * multiplier)
|
||||
}
|
||||
|
||||
// PrettyJSON get pretty Json string
|
||||
func PrettyJSON(v any) (string, error) {
|
||||
out, err := json.MarshalIndent(v, "", " ")
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
// StringsToInts string slice to int slice.
|
||||
// Deprecated: please use the arrutil.StringsToInts()
|
||||
func StringsToInts(ss []string) (ints []int, err error) {
|
||||
for _, str := range ss {
|
||||
iVal, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return []int{}, err
|
||||
}
|
||||
|
||||
ints = append(ints, iVal)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ArgsWithSpaces it like Println, will add spaces for each argument
|
||||
func ArgsWithSpaces(args []any) (message string) {
|
||||
if ln := len(args); ln == 0 {
|
||||
message = ""
|
||||
} else if ln == 1 {
|
||||
message = fmt.Sprint(args[0])
|
||||
} else {
|
||||
message = fmt.Sprintln(args...)
|
||||
// clear last "\n"
|
||||
message = message[:len(message)-1]
|
||||
}
|
||||
return
|
||||
}
|
||||
136
vendor/github.com/gookit/goutil/fsutil/README.md
generated
vendored
Normal file
136
vendor/github.com/gookit/goutil/fsutil/README.md
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
# FileSystem Util
|
||||
|
||||
`fsutil` Provide some commonly file system util functions.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
go get github.com/gookit/goutil/fsutil
|
||||
```
|
||||
|
||||
## Go docs
|
||||
|
||||
- [Go docs](https://pkg.go.dev/github.com/gookit/goutil/fsutil)
|
||||
|
||||
## Find files
|
||||
|
||||
```go
|
||||
// find all files in dir
|
||||
fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error {
|
||||
fmt.Println(filePath)
|
||||
return nil
|
||||
})
|
||||
|
||||
// find files with filters
|
||||
fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error {
|
||||
fmt.Println(filePath)
|
||||
return nil
|
||||
}, fsutil.ExcludeDotFile)
|
||||
```
|
||||
|
||||
## Functions API
|
||||
|
||||
> **Note**: doc by run `go doc ./fsutil`
|
||||
|
||||
```go
|
||||
func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool
|
||||
func CopyFile(srcPath, dstPath string) error
|
||||
func CreateFile(fpath string, filePerm, dirPerm os.FileMode, fileFlag ...int) (*os.File, error)
|
||||
func DeleteIfExist(fPath string) error
|
||||
func DeleteIfFileExist(fPath string) error
|
||||
func Dir(fpath string) string
|
||||
func DiscardReader(src io.Reader)
|
||||
func ExcludeDotFile(_ string, ent fs.DirEntry) bool
|
||||
func Expand(pathStr string) string
|
||||
func ExpandPath(pathStr string) string
|
||||
func Extname(fpath string) string
|
||||
func FileExists(path string) bool
|
||||
func FileExt(fpath string) string
|
||||
func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error)
|
||||
func GetContents(in any) []byte
|
||||
func GlobWithFunc(pattern string, fn func(filePath string) error) (err error)
|
||||
func IsAbsPath(aPath string) bool
|
||||
func IsDir(path string) bool
|
||||
func IsFile(path string) bool
|
||||
func IsImageFile(path string) bool
|
||||
func IsZipFile(filepath string) bool
|
||||
func JoinPaths(elem ...string) string
|
||||
func JoinSubPaths(basePath string, elem ...string) string
|
||||
func LineScanner(in any) *bufio.Scanner
|
||||
func MimeType(path string) (mime string)
|
||||
func MkDirs(perm os.FileMode, dirPaths ...string) error
|
||||
func MkParentDir(fpath string) error
|
||||
func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error
|
||||
func Mkdir(dirPath string, perm os.FileMode) error
|
||||
func MustCopyFile(srcPath, dstPath string)
|
||||
func MustCreateFile(filePath string, filePerm, dirPerm os.FileMode) *os.File
|
||||
func MustReadFile(filePath string) []byte
|
||||
func MustReadReader(r io.Reader) []byte
|
||||
func MustRemove(fPath string)
|
||||
func Name(fpath string) string
|
||||
func NewIOReader(in any) (r io.Reader, err error)
|
||||
func OSTempDir(pattern string) (string, error)
|
||||
func OSTempFile(pattern string) (*os.File, error)
|
||||
func OnlyFindDir(_ string, ent fs.DirEntry) bool
|
||||
func OnlyFindFile(_ string, ent fs.DirEntry) bool
|
||||
func OpenAppendFile(filepath string) (*os.File, error)
|
||||
func OpenFile(filepath string, flag int, perm os.FileMode) (*os.File, error)
|
||||
func OpenReadFile(filepath string) (*os.File, error)
|
||||
func OpenTruncFile(filepath string) (*os.File, error)
|
||||
func PathExists(path string) bool
|
||||
func PathMatch(pattern, s string) bool
|
||||
func PathName(fpath string) string
|
||||
func PutContents(filePath string, data any, fileFlag ...int) (int, error)
|
||||
func QuickOpenFile(filepath string, fileFlag ...int) (*os.File, error)
|
||||
func QuietRemove(fPath string)
|
||||
func ReadAll(in any) []byte
|
||||
func ReadExistFile(filePath string) []byte
|
||||
func ReadFile(filePath string) []byte
|
||||
func ReadOrErr(in any) ([]byte, error)
|
||||
func ReadReader(r io.Reader) []byte
|
||||
func ReadString(in any) string
|
||||
func ReadStringOrErr(in any) (string, error)
|
||||
func ReaderMimeType(r io.Reader) (mime string)
|
||||
func Realpath(pathStr string) string
|
||||
func Remove(fPath string) error
|
||||
func ResolvePath(pathStr string) string
|
||||
func RmFileIfExist(fPath string) error
|
||||
func RmIfExist(fPath string) error
|
||||
func SearchNameUp(dirPath, name string) string
|
||||
func SearchNameUpx(dirPath, name string) (string, bool)
|
||||
func SlashPath(path string) string
|
||||
func SplitPath(pathStr string) (dir, name string)
|
||||
func Suffix(fpath string) string
|
||||
func TempDir(dir, pattern string) (string, error)
|
||||
func TempFile(dir, pattern string) (*os.File, error)
|
||||
func TextScanner(in any) *scanner.Scanner
|
||||
func ToAbsPath(p string) string
|
||||
func UnixPath(path string) string
|
||||
func Unzip(archive, targetDir string) (err error)
|
||||
func WalkDir(dir string, fn fs.WalkDirFunc) error
|
||||
func WriteFile(filePath string, data any, perm os.FileMode, fileFlag ...int) error
|
||||
func WriteOSFile(f *os.File, data any) (n int, err error)
|
||||
type FilterFunc func(fPath string, ent fs.DirEntry) bool
|
||||
func ExcludeSuffix(ss ...string) FilterFunc
|
||||
func IncludeSuffix(ss ...string) FilterFunc
|
||||
type HandleFunc func(fPath string, ent fs.DirEntry) error
|
||||
```
|
||||
|
||||
## Code Check & Testing
|
||||
|
||||
```bash
|
||||
gofmt -w -l ./
|
||||
golint ./...
|
||||
```
|
||||
|
||||
**Testing**:
|
||||
|
||||
```shell
|
||||
go test -v ./fsutil/...
|
||||
```
|
||||
|
||||
**Test limit by regexp**:
|
||||
|
||||
```shell
|
||||
go test -v -run ^TestSetByKeys ./fsutil/...
|
||||
```
|
||||
26
vendor/github.com/gookit/goutil/fsutil/check.go
generated
vendored
26
vendor/github.com/gookit/goutil/fsutil/check.go
generated
vendored
@@ -4,14 +4,17 @@ import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// perm for create dir or file
|
||||
var (
|
||||
// DefaultDirPerm perm and flags for create log file
|
||||
DefaultDirPerm os.FileMode = 0775
|
||||
DefaultFilePerm os.FileMode = 0665
|
||||
OnlyReadFilePerm os.FileMode = 0444
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultFileFlags for create and write
|
||||
DefaultFileFlags = os.O_CREATE | os.O_WRONLY | os.O_APPEND
|
||||
// OnlyReadFileFlags open file for read
|
||||
@@ -41,7 +44,7 @@ func PathExists(path string) bool {
|
||||
|
||||
// IsDir reports whether the named directory exists.
|
||||
func IsDir(path string) bool {
|
||||
if path == "" {
|
||||
if path == "" || len(path) > 468 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -58,7 +61,7 @@ func FileExists(path string) bool {
|
||||
|
||||
// IsFile reports whether the named file or directory exists.
|
||||
func IsFile(path string) bool {
|
||||
if path == "" {
|
||||
if path == "" || len(path) > 468 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -70,7 +73,13 @@ func IsFile(path string) bool {
|
||||
|
||||
// IsAbsPath is abs path.
|
||||
func IsAbsPath(aPath string) bool {
|
||||
return path.IsAbs(aPath)
|
||||
if len(aPath) > 0 {
|
||||
if aPath[0] == '/' {
|
||||
return true
|
||||
}
|
||||
return filepath.IsAbs(aPath)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ImageMimeTypes refer net/http package
|
||||
@@ -118,3 +127,12 @@ func IsZipFile(filepath string) bool {
|
||||
|
||||
return bytes.Equal(buf, []byte("PK\x03\x04"))
|
||||
}
|
||||
|
||||
// PathMatch check for a string. alias of path.Match()
|
||||
func PathMatch(pattern, s string) bool {
|
||||
ok, err := path.Match(pattern, s)
|
||||
if err != nil {
|
||||
ok = false
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
156
vendor/github.com/gookit/goutil/fsutil/find.go
generated
vendored
Normal file
156
vendor/github.com/gookit/goutil/fsutil/find.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gookit/goutil/arrutil"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// SearchNameUp find file/dir name in dirPath or parent dirs,
|
||||
// return the name of directory path
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// repoDir := fsutil.SearchNameUp("/path/to/dir", ".git")
|
||||
func SearchNameUp(dirPath, name string) string {
|
||||
dir, _ := SearchNameUpx(dirPath, name)
|
||||
return dir
|
||||
}
|
||||
|
||||
// SearchNameUpx find file/dir name in dirPath or parent dirs,
|
||||
// return the name of directory path and dir is changed.
|
||||
func SearchNameUpx(dirPath, name string) (string, bool) {
|
||||
var level int
|
||||
dirPath = ToAbsPath(dirPath)
|
||||
|
||||
for {
|
||||
namePath := filepath.Join(dirPath, name)
|
||||
if PathExists(namePath) {
|
||||
return dirPath, level > 0
|
||||
}
|
||||
|
||||
level++
|
||||
prevLn := len(dirPath)
|
||||
dirPath = filepath.Dir(dirPath)
|
||||
if prevLn == len(dirPath) {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WalkDir walks the file tree rooted at root, calling fn for each file or
|
||||
// directory in the tree, including root.
|
||||
func WalkDir(dir string, fn fs.WalkDirFunc) error {
|
||||
return filepath.WalkDir(dir, fn)
|
||||
}
|
||||
|
||||
// GlobWithFunc handle matched file
|
||||
//
|
||||
// - TIP: will be not find in subdir.
|
||||
func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) {
|
||||
files, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, filePath := range files {
|
||||
err = fn(filePath)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
// FilterFunc type for FindInDir
|
||||
//
|
||||
// - return False will skip handle the file.
|
||||
FilterFunc func(fPath string, ent fs.DirEntry) bool
|
||||
|
||||
// HandleFunc type for FindInDir
|
||||
HandleFunc func(fPath string, ent fs.DirEntry) error
|
||||
)
|
||||
|
||||
// OnlyFindDir on find
|
||||
func OnlyFindDir(_ string, ent fs.DirEntry) bool {
|
||||
return ent.IsDir()
|
||||
}
|
||||
|
||||
// OnlyFindFile on find
|
||||
func OnlyFindFile(_ string, ent fs.DirEntry) bool {
|
||||
return !ent.IsDir()
|
||||
}
|
||||
|
||||
// ExcludeNames on find
|
||||
func ExcludeNames(names ...string) FilterFunc {
|
||||
return func(_ string, ent fs.DirEntry) bool {
|
||||
return !arrutil.StringsHas(names, ent.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// IncludeSuffix on find
|
||||
func IncludeSuffix(ss ...string) FilterFunc {
|
||||
return func(_ string, ent fs.DirEntry) bool {
|
||||
return strutil.HasOneSuffix(ent.Name(), ss)
|
||||
}
|
||||
}
|
||||
|
||||
// ExcludeDotFile on find
|
||||
func ExcludeDotFile(_ string, ent fs.DirEntry) bool {
|
||||
return ent.Name()[0] != '.'
|
||||
}
|
||||
|
||||
// ExcludeSuffix on find
|
||||
func ExcludeSuffix(ss ...string) FilterFunc {
|
||||
return func(_ string, ent fs.DirEntry) bool {
|
||||
return !strutil.HasOneSuffix(ent.Name(), ss)
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyFilters handle
|
||||
func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool {
|
||||
for _, filter := range filters {
|
||||
if !filter(fPath, ent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// FindInDir code refer the go pkg: path/filepath.glob()
|
||||
//
|
||||
// - TIP: will be not find in subdir.
|
||||
//
|
||||
// filters: return false will skip the file.
|
||||
func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) {
|
||||
fi, err := os.Stat(dir)
|
||||
if err != nil || !fi.IsDir() {
|
||||
return // ignore I/O error
|
||||
}
|
||||
|
||||
// names, _ := d.Readdirnames(-1)
|
||||
// sort.Strings(names)
|
||||
|
||||
des, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, ent := range des {
|
||||
filePath := dir + "/" + ent.Name()
|
||||
|
||||
// apply filters
|
||||
if len(filters) > 0 && ApplyFilters(filePath, ent, filters) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := handleFn(filePath, ent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
50
vendor/github.com/gookit/goutil/fsutil/fsutil.go
generated
vendored
50
vendor/github.com/gookit/goutil/fsutil/fsutil.go
generated
vendored
@@ -5,6 +5,10 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -77,3 +81,49 @@ func ReaderMimeType(r io.Reader) (mime string) {
|
||||
|
||||
return http.DetectContentType(buf[:n])
|
||||
}
|
||||
|
||||
// JoinPaths elements, alias of filepath.Join()
|
||||
func JoinPaths(elem ...string) string {
|
||||
return filepath.Join(elem...)
|
||||
}
|
||||
|
||||
// JoinSubPaths elements, like the filepath.Join()
|
||||
func JoinSubPaths(basePath string, elem ...string) string {
|
||||
paths := make([]string, len(elem)+1)
|
||||
paths[0] = basePath
|
||||
copy(paths[1:], elem)
|
||||
return filepath.Join(paths...)
|
||||
}
|
||||
|
||||
// SlashPath alias of filepath.ToSlash
|
||||
func SlashPath(path string) string {
|
||||
return filepath.ToSlash(path)
|
||||
}
|
||||
|
||||
// UnixPath like of filepath.ToSlash, but always replace
|
||||
func UnixPath(path string) string {
|
||||
if !strings.ContainsRune(path, '\\') {
|
||||
return path
|
||||
}
|
||||
return strings.ReplaceAll(path, "\\", "/")
|
||||
}
|
||||
|
||||
// ToAbsPath convert process. will expand home dir
|
||||
//
|
||||
// TIP: will don't check path
|
||||
func ToAbsPath(p string) string {
|
||||
if len(p) == 0 || IsAbsPath(p) {
|
||||
return p
|
||||
}
|
||||
|
||||
// expand home dir
|
||||
if p[0] == '~' {
|
||||
return comfunc.ExpandHome(p)
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return p
|
||||
}
|
||||
return filepath.Join(wd, p)
|
||||
}
|
||||
|
||||
119
vendor/github.com/gookit/goutil/fsutil/info.go
generated
vendored
119
vendor/github.com/gookit/goutil/fsutil/info.go
generated
vendored
@@ -1,7 +1,6 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -9,116 +8,60 @@ import (
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// Dir get dir path, without last name.
|
||||
func Dir(fpath string) string {
|
||||
return filepath.Dir(fpath)
|
||||
}
|
||||
// Dir get dir path from filepath, without last name.
|
||||
func Dir(fpath string) string { return filepath.Dir(fpath) }
|
||||
|
||||
// PathName get file/dir name from full path
|
||||
func PathName(fpath string) string {
|
||||
return path.Base(fpath)
|
||||
}
|
||||
func PathName(fpath string) string { return path.Base(fpath) }
|
||||
|
||||
// Name get file/dir name from full path
|
||||
// Name get file/dir name from full path.
|
||||
//
|
||||
// eg: path/to/main.go => main.go
|
||||
func Name(fpath string) string {
|
||||
if fpath == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Base(fpath)
|
||||
}
|
||||
|
||||
// FileExt get filename ext. alias of path.Ext()
|
||||
func FileExt(fpath string) string {
|
||||
return path.Ext(fpath)
|
||||
//
|
||||
// eg: path/to/main.go => ".go"
|
||||
func FileExt(fpath string) string { return path.Ext(fpath) }
|
||||
|
||||
// Extname get filename ext. alias of path.Ext()
|
||||
//
|
||||
// eg: path/to/main.go => "go"
|
||||
func Extname(fpath string) string {
|
||||
if ext := path.Ext(fpath); len(ext) > 0 {
|
||||
return ext[1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Suffix get filename ext. alias of path.Ext()
|
||||
func Suffix(fpath string) string {
|
||||
return path.Ext(fpath)
|
||||
}
|
||||
//
|
||||
// eg: path/to/main.go => ".go"
|
||||
func Suffix(fpath string) string { return path.Ext(fpath) }
|
||||
|
||||
// Expand will parse first `~` as user home dir path.
|
||||
func Expand(pathStr string) string {
|
||||
return comfunc.ExpandPath(pathStr)
|
||||
return comfunc.ExpandHome(pathStr)
|
||||
}
|
||||
|
||||
// ExpandPath will parse `~` as user home dir path.
|
||||
func ExpandPath(pathStr string) string {
|
||||
return comfunc.ExpandPath(pathStr)
|
||||
return comfunc.ExpandHome(pathStr)
|
||||
}
|
||||
|
||||
// Realpath returns the shortest path name equivalent to path by purely lexical processing.
|
||||
func Realpath(pathStr string) string {
|
||||
return path.Clean(pathStr)
|
||||
// ResolvePath will parse `~` and env var in path
|
||||
func ResolvePath(pathStr string) string {
|
||||
pathStr = comfunc.ExpandHome(pathStr)
|
||||
// return comfunc.ParseEnvVar()
|
||||
return os.ExpandEnv(pathStr)
|
||||
}
|
||||
|
||||
// SplitPath splits path immediately following the final Separator, separating it into a directory and file name component
|
||||
func SplitPath(pathStr string) (dir, name string) {
|
||||
return filepath.Split(pathStr)
|
||||
}
|
||||
|
||||
// GlobWithFunc handle matched file
|
||||
func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) {
|
||||
files, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, filePath := range files {
|
||||
err = fn(filePath)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
// FilterFunc type for FindInDir
|
||||
FilterFunc func(fPath string, fi os.FileInfo) bool
|
||||
// HandleFunc type for FindInDir
|
||||
HandleFunc func(fPath string, fi os.FileInfo) error
|
||||
)
|
||||
|
||||
// FindInDir code refer the go pkg: path/filepath.glob()
|
||||
//
|
||||
// filters: return false will skip the file.
|
||||
func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) {
|
||||
fi, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return // ignore I/O error
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return // ignore I/O error
|
||||
}
|
||||
|
||||
// names, _ := d.Readdirnames(-1)
|
||||
// sort.Strings(names)
|
||||
|
||||
stats, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, fi := range stats {
|
||||
baseName := fi.Name()
|
||||
filePath := dir + "/" + baseName
|
||||
|
||||
// call filters
|
||||
if len(filters) > 0 {
|
||||
var filtered = false
|
||||
for _, filter := range filters {
|
||||
if !filter(filePath, fi) {
|
||||
filtered = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if filtered {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := handleFn(filePath, fi); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
19
vendor/github.com/gookit/goutil/fsutil/info_nonwin.go
generated
vendored
Normal file
19
vendor/github.com/gookit/goutil/fsutil/info_nonwin.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
//go:build !windows
|
||||
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// Realpath returns the shortest path name equivalent to path by purely lexical processing.
|
||||
func Realpath(pathStr string) string {
|
||||
pathStr = comfunc.ExpandHome(pathStr)
|
||||
|
||||
if !IsAbsPath(pathStr) {
|
||||
pathStr = JoinSubPaths(comfunc.Workdir(), pathStr)
|
||||
}
|
||||
return path.Clean(pathStr)
|
||||
}
|
||||
17
vendor/github.com/gookit/goutil/fsutil/info_windows.go
generated
vendored
Normal file
17
vendor/github.com/gookit/goutil/fsutil/info_windows.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// Realpath returns the shortest path name equivalent to path by purely lexical processing.
|
||||
func Realpath(pathStr string) string {
|
||||
pathStr = comfunc.ExpandHome(pathStr)
|
||||
|
||||
if !IsAbsPath(pathStr) {
|
||||
pathStr = JoinSubPaths(comfunc.Workdir(), pathStr)
|
||||
}
|
||||
return filepath.Clean(pathStr)
|
||||
}
|
||||
234
vendor/github.com/gookit/goutil/fsutil/operate.go
generated
vendored
234
vendor/github.com/gookit/goutil/fsutil/operate.go
generated
vendored
@@ -4,11 +4,13 @@ import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/basefn"
|
||||
)
|
||||
|
||||
// Mkdir alias of os.MkdirAll()
|
||||
@@ -16,6 +18,27 @@ func Mkdir(dirPath string, perm os.FileMode) error {
|
||||
return os.MkdirAll(dirPath, perm)
|
||||
}
|
||||
|
||||
// MkDirs batch make multi dirs at once
|
||||
func MkDirs(perm os.FileMode, dirPaths ...string) error {
|
||||
for _, dirPath := range dirPaths {
|
||||
if err := os.MkdirAll(dirPath, perm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkSubDirs batch make multi sub-dirs at once
|
||||
func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error {
|
||||
for _, dirName := range subDirs {
|
||||
dirPath := parentDir + "/" + dirName
|
||||
if err := os.MkdirAll(dirPath, perm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkParentDir quick create parent dir
|
||||
func MkParentDir(fpath string) error {
|
||||
dirPath := filepath.Dir(fpath)
|
||||
@@ -25,61 +48,11 @@ func MkParentDir(fpath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscardReader anything from the reader
|
||||
func DiscardReader(src io.Reader) {
|
||||
_, _ = io.Copy(ioutil.Discard, src)
|
||||
}
|
||||
|
||||
// MustReadFile read file contents, will panic on error
|
||||
func MustReadFile(filePath string) []byte {
|
||||
bs, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
// MustReadReader read contents from io.Reader, will panic on error
|
||||
func MustReadReader(r io.Reader) []byte {
|
||||
// TODO go 1.16+ bs, err := io.ReadAll(r)
|
||||
bs, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
// GetContents read contents from path or io.Reader, will panic on error
|
||||
func GetContents(in any) []byte {
|
||||
if fPath, ok := in.(string); ok {
|
||||
return MustReadFile(fPath)
|
||||
}
|
||||
|
||||
if r, ok := in.(io.Reader); ok {
|
||||
return MustReadReader(r)
|
||||
}
|
||||
|
||||
panic("invalid type of input")
|
||||
}
|
||||
|
||||
// ReadExistFile read file contents if existed, will panic on error
|
||||
func ReadExistFile(filePath string) []byte {
|
||||
if IsFile(filePath) {
|
||||
bs, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// open/create files
|
||||
// ************************************************************
|
||||
|
||||
// some flag consts for open file
|
||||
// some commonly flag consts for open file
|
||||
const (
|
||||
FsCWAFlags = os.O_CREATE | os.O_WRONLY | os.O_APPEND // create, append write-only
|
||||
FsCWTFlags = os.O_CREATE | os.O_WRONLY | os.O_TRUNC // create, override write-only
|
||||
@@ -88,6 +61,10 @@ const (
|
||||
)
|
||||
|
||||
// OpenFile like os.OpenFile, but will auto create dir.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// file, err := OpenFile("path/to/file.txt", FsCWFlags, 0666)
|
||||
func OpenFile(filepath string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
fileDir := path.Dir(filepath)
|
||||
if err := os.MkdirAll(fileDir, DefaultDirPerm); err != nil {
|
||||
@@ -101,20 +78,39 @@ func OpenFile(filepath string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
return file, nil
|
||||
}
|
||||
|
||||
/* TODO MustOpenFile() */
|
||||
|
||||
// QuickOpenFile like os.OpenFile, open for write, if not exists, will create it.
|
||||
// MustOpenFile like os.OpenFile, but will auto create dir.
|
||||
//
|
||||
// Tip: file flag default is FsCWAFlags
|
||||
func QuickOpenFile(filepath string, fileFlag ...int) (*os.File, error) {
|
||||
flag := FsCWAFlags
|
||||
if len(fileFlag) > 0 {
|
||||
flag = fileFlag[0]
|
||||
// Usage:
|
||||
//
|
||||
// file := MustOpenFile("path/to/file.txt", FsCWFlags, 0666)
|
||||
func MustOpenFile(filepath string, flag int, perm os.FileMode) *os.File {
|
||||
file, err := OpenFile(filepath, flag, perm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
// QuickOpenFile like os.OpenFile, open for append write. if not exists, will create it.
|
||||
//
|
||||
// Alias of OpenAppendFile()
|
||||
func QuickOpenFile(filepath string, fileFlag ...int) (*os.File, error) {
|
||||
flag := basefn.FirstOr(fileFlag, FsCWAFlags)
|
||||
return OpenFile(filepath, flag, DefaultFilePerm)
|
||||
}
|
||||
|
||||
// OpenAppendFile like os.OpenFile, open for append write. if not exists, will create it.
|
||||
func OpenAppendFile(filepath string, filePerm ...os.FileMode) (*os.File, error) {
|
||||
perm := basefn.FirstOr(filePerm, DefaultFilePerm)
|
||||
return OpenFile(filepath, FsCWAFlags, perm)
|
||||
}
|
||||
|
||||
// OpenTruncFile like os.OpenFile, open for override write. if not exists, will create it.
|
||||
func OpenTruncFile(filepath string, filePerm ...os.FileMode) (*os.File, error) {
|
||||
perm := basefn.FirstOr(filePerm, DefaultFilePerm)
|
||||
return OpenFile(filepath, FsCWTFlags, perm)
|
||||
}
|
||||
|
||||
// OpenReadFile like os.OpenFile, open file for read contents
|
||||
func OpenReadFile(filepath string) (*os.File, error) {
|
||||
return os.OpenFile(filepath, FsRFlags, OnlyReadFilePerm)
|
||||
@@ -134,11 +130,7 @@ func CreateFile(fpath string, filePerm, dirPerm os.FileMode, fileFlag ...int) (*
|
||||
}
|
||||
}
|
||||
|
||||
flag := FsCWTFlags
|
||||
if len(fileFlag) > 0 {
|
||||
flag = fileFlag[0]
|
||||
}
|
||||
|
||||
flag := basefn.FirstOr(fileFlag, FsCWAFlags)
|
||||
return os.OpenFile(fpath, flag, filePerm)
|
||||
}
|
||||
|
||||
@@ -151,105 +143,6 @@ func MustCreateFile(filePath string, filePerm, dirPerm os.FileMode) *os.File {
|
||||
return file
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// write, copy files
|
||||
// ************************************************************
|
||||
|
||||
// PutContents create file and write contents to file at once.
|
||||
//
|
||||
// data type allow: string, []byte, io.Reader
|
||||
//
|
||||
// Tip: file flag default is FsCWAFlags
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// fsutil.PutContents(filePath, contents, fsutil.FsCWTFlags)
|
||||
func PutContents(filePath string, data any, fileFlag ...int) (int, error) {
|
||||
// create and open file
|
||||
dstFile, err := QuickOpenFile(filePath, fileFlag...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
defer dstFile.Close()
|
||||
switch typData := data.(type) {
|
||||
case []byte:
|
||||
return dstFile.Write(typData)
|
||||
case string:
|
||||
return dstFile.WriteString(typData)
|
||||
case io.Reader: // eg: buffer
|
||||
n, err := io.Copy(dstFile, typData)
|
||||
return int(n), err
|
||||
default:
|
||||
panic("PutContents: data type only allow: []byte, string, io.Reader")
|
||||
}
|
||||
}
|
||||
|
||||
// WriteFile create file and write contents to file, can set perm for file.
|
||||
//
|
||||
// data type allow: string, []byte, io.Reader
|
||||
//
|
||||
// Tip: file flag default is FsCWTFlags
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// fsutil.WriteFile(filePath, contents, 0666, fsutil.FsCWAFlags)
|
||||
func WriteFile(filePath string, data any, perm os.FileMode, fileFlag ...int) error {
|
||||
flag := FsCWTFlags
|
||||
if len(fileFlag) > 0 {
|
||||
flag = fileFlag[0]
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(filePath, flag, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch typData := data.(type) {
|
||||
case []byte:
|
||||
_, err = f.Write(typData)
|
||||
case string:
|
||||
_, err = f.WriteString(typData)
|
||||
case io.Reader: // eg: buffer
|
||||
_, err = io.Copy(f, typData)
|
||||
default:
|
||||
_ = f.Close()
|
||||
panic("WriteFile: data type only allow: []byte, string, io.Reader")
|
||||
}
|
||||
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CopyFile copy a file to another file path.
|
||||
func CopyFile(srcPath, dstPath string) error {
|
||||
srcFile, err := os.OpenFile(srcPath, FsRFlags, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// create and open file
|
||||
dstFile, err := QuickOpenFile(dstPath, FsCWTFlags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
_, err = io.Copy(dstFile, srcFile)
|
||||
return err
|
||||
}
|
||||
|
||||
// MustCopyFile copy file to another path.
|
||||
func MustCopyFile(srcPath, dstPath string) {
|
||||
err := CopyFile(srcPath, dstPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// remove files
|
||||
// ************************************************************
|
||||
@@ -302,6 +195,18 @@ func DeleteIfFileExist(fPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveSub removes all sub files and dirs of dirPath, but not remove dirPath.
|
||||
func RemoveSub(dirPath string, fns ...FilterFunc) error {
|
||||
return FindInDir(dirPath, func(fPath string, ent fs.DirEntry) error {
|
||||
if ent.IsDir() {
|
||||
if err := RemoveSub(fPath, fns...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return os.Remove(fPath)
|
||||
}, fns...)
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// other operates
|
||||
// ************************************************************
|
||||
@@ -319,7 +224,6 @@ func Unzip(archive, targetDir string) (err error) {
|
||||
}
|
||||
|
||||
for _, file := range reader.File {
|
||||
|
||||
if strings.Contains(file.Name, "..") {
|
||||
return fmt.Errorf("illegal file path in zip: %v", file.Name)
|
||||
}
|
||||
|
||||
137
vendor/github.com/gookit/goutil/fsutil/opread.go
generated
vendored
Normal file
137
vendor/github.com/gookit/goutil/fsutil/opread.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"text/scanner"
|
||||
)
|
||||
|
||||
// NewIOReader instance by input file path or io.Reader
|
||||
func NewIOReader(in any) (r io.Reader, err error) {
|
||||
switch typIn := in.(type) {
|
||||
case string: // as file path
|
||||
return OpenReadFile(typIn)
|
||||
case io.Reader:
|
||||
return typIn, nil
|
||||
}
|
||||
return nil, errors.New("invalid input type, allow: string, io.Reader")
|
||||
}
|
||||
|
||||
// DiscardReader anything from the reader
|
||||
func DiscardReader(src io.Reader) {
|
||||
_, _ = io.Copy(io.Discard, src)
|
||||
}
|
||||
|
||||
// ReadFile read file contents, will panic on error
|
||||
func ReadFile(filePath string) []byte {
|
||||
return MustReadFile(filePath)
|
||||
}
|
||||
|
||||
// MustReadFile read file contents, will panic on error
|
||||
func MustReadFile(filePath string) []byte {
|
||||
bs, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
// ReadReader read contents from io.Reader, will panic on error
|
||||
func ReadReader(r io.Reader) []byte { return MustReadReader(r) }
|
||||
|
||||
// MustReadReader read contents from io.Reader, will panic on error
|
||||
func MustReadReader(r io.Reader) []byte {
|
||||
bs, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
// ReadString read contents from path or io.Reader, will panic on in type error
|
||||
func ReadString(in any) string {
|
||||
return string(GetContents(in))
|
||||
}
|
||||
|
||||
// ReadStringOrErr read contents from path or io.Reader, will panic on in type error
|
||||
func ReadStringOrErr(in any) (string, error) {
|
||||
r, err := NewIOReader(in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
bs, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bs), nil
|
||||
}
|
||||
|
||||
// ReadAll read contents from path or io.Reader, will panic on in type error
|
||||
func ReadAll(in any) []byte { return GetContents(in) }
|
||||
|
||||
// GetContents read contents from path or io.Reader, will panic on in type error
|
||||
func GetContents(in any) []byte {
|
||||
r, err := NewIOReader(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return MustReadReader(r)
|
||||
}
|
||||
|
||||
// ReadOrErr read contents from path or io.Reader, will panic on in type error
|
||||
func ReadOrErr(in any) ([]byte, error) {
|
||||
r, err := NewIOReader(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
// ReadExistFile read file contents if existed, will panic on error
|
||||
func ReadExistFile(filePath string) []byte {
|
||||
if IsFile(filePath) {
|
||||
bs, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TextScanner from filepath or io.Reader, will panic on in type error
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// s := fsutil.TextScanner("/path/to/file")
|
||||
// for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
|
||||
// fmt.Printf("%s: %s\n", s.Position, s.TokenText())
|
||||
// }
|
||||
func TextScanner(in any) *scanner.Scanner {
|
||||
var s scanner.Scanner
|
||||
r, err := NewIOReader(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s.Init(r)
|
||||
s.Filename = "text-scanner"
|
||||
return &s
|
||||
}
|
||||
|
||||
// LineScanner create from filepath or io.Reader
|
||||
//
|
||||
// s := fsutil.LineScanner("/path/to/file")
|
||||
// for s.Scan() {
|
||||
// fmt.Println(s.Text())
|
||||
// }
|
||||
func LineScanner(in any) *bufio.Scanner {
|
||||
r, err := NewIOReader(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bufio.NewScanner(r)
|
||||
}
|
||||
101
vendor/github.com/gookit/goutil/fsutil/opwrite.go
generated
vendored
Normal file
101
vendor/github.com/gookit/goutil/fsutil/opwrite.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/gookit/goutil/basefn"
|
||||
)
|
||||
|
||||
// ************************************************************
|
||||
// write, copy files
|
||||
// ************************************************************
|
||||
|
||||
// PutContents create file and write contents to file at once.
|
||||
//
|
||||
// data type allow: string, []byte, io.Reader
|
||||
//
|
||||
// Tip: file flag default is FsCWTFlags (override write)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// fsutil.PutContents(filePath, contents, fsutil.FsCWAFlags) // append write
|
||||
func PutContents(filePath string, data any, fileFlag ...int) (int, error) {
|
||||
f, err := QuickOpenFile(filePath, basefn.FirstOr(fileFlag, FsCWTFlags))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return WriteOSFile(f, data)
|
||||
}
|
||||
|
||||
// WriteFile create file and write contents to file, can set perm for file.
|
||||
//
|
||||
// data type allow: string, []byte, io.Reader
|
||||
//
|
||||
// Tip: file flag default is FsCWTFlags (override write)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// fsutil.WriteFile(filePath, contents, fsutil.DefaultFilePerm, fsutil.FsCWAFlags)
|
||||
func WriteFile(filePath string, data any, perm os.FileMode, fileFlag ...int) error {
|
||||
flag := basefn.FirstOr(fileFlag, FsCWTFlags)
|
||||
f, err := OpenFile(filePath, flag, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = WriteOSFile(f, data)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteOSFile write data to give os.File, then close file.
|
||||
//
|
||||
// data type allow: string, []byte, io.Reader
|
||||
func WriteOSFile(f *os.File, data any) (n int, err error) {
|
||||
switch typData := data.(type) {
|
||||
case []byte:
|
||||
n, err = f.Write(typData)
|
||||
case string:
|
||||
n, err = f.WriteString(typData)
|
||||
case io.Reader: // eg: buffer
|
||||
var n64 int64
|
||||
n64, err = io.Copy(f, typData)
|
||||
n = int(n64)
|
||||
default:
|
||||
_ = f.Close()
|
||||
panic("WriteFile: data type only allow: []byte, string, io.Reader")
|
||||
}
|
||||
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// CopyFile copy a file to another file path.
|
||||
func CopyFile(srcPath, dstPath string) error {
|
||||
srcFile, err := os.OpenFile(srcPath, FsRFlags, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// create and open file
|
||||
dstFile, err := QuickOpenFile(dstPath, FsCWTFlags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
_, err = io.Copy(dstFile, srcFile)
|
||||
return err
|
||||
}
|
||||
|
||||
// MustCopyFile copy file to another path.
|
||||
func MustCopyFile(srcPath, dstPath string) {
|
||||
err := CopyFile(srcPath, dstPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user