vendor: make vendor-update

This commit is contained in:
Aliaksandr Valialkin 2022-05-25 21:49:12 +03:00
parent f6d11a49aa
commit 31c6cfe3fb
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
71 changed files with 1452 additions and 2407 deletions

18
go.mod
View file

@ -11,7 +11,7 @@ require (
github.com/VictoriaMetrics/fasthttp v1.1.0
github.com/VictoriaMetrics/metrics v1.18.1
github.com/VictoriaMetrics/metricsql v0.43.0
github.com/aws/aws-sdk-go v1.44.18
github.com/aws/aws-sdk-go v1.44.22
github.com/cespare/xxhash/v2 v2.1.2
// TODO: switch back to https://github.com/cheggaaa/pb/v3 when v3-pooling branch
@ -22,25 +22,24 @@ require (
github.com/influxdata/influxdb v1.9.7
github.com/klauspost/compress v1.15.4
github.com/prometheus/prometheus v1.8.2-0.20201119142752-3ad25a6dc3d9
github.com/urfave/cli/v2 v2.7.1
github.com/urfave/cli/v2 v2.8.1
github.com/valyala/fastjson v1.6.3
github.com/valyala/fastrand v1.1.0
github.com/valyala/fasttemplate v1.2.1
github.com/valyala/gozstd v1.17.0
github.com/valyala/quicktemplate v1.7.0
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
golang.org/x/sys v0.0.0-20220519141025-dcacdad47464
google.golang.org/api v0.80.0
golang.org/x/net v0.0.0-20220524220425-1d687d428aca
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
google.golang.org/api v0.81.0
gopkg.in/yaml.v2 v2.4.0
)
require (
cloud.google.com/go v0.101.1 // indirect
cloud.google.com/go v0.102.0 // indirect
cloud.google.com/go/compute v1.6.1 // indirect
cloud.google.com/go/iam v0.3.0 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/fatih/color v1.13.0 // indirect
@ -68,6 +67,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 // indirect
@ -75,7 +75,7 @@ require (
golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
google.golang.org/genproto v0.0.0-20220525015930-6ca3db687a9d // indirect
google.golang.org/grpc v1.46.2 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

40
go.sum
View file

@ -29,8 +29,8 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.101.1 h1:3+/0TAm9JD/PyhkrDWQWi2L197h3euCsM+H+J4iYTR8=
cloud.google.com/go v0.101.1/go.mod h1:55HwjsGW4CHD3JrNuMdZtSDsgTs0CuCB/bBTugD+7AA=
cloud.google.com/go v0.102.0 h1:DAq3r8y4mDgyB/ZPJ9v/5VJNqjgJAxTn6ZYLlUywOu8=
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -57,7 +57,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.22.0/go.mod h1:GbaLEoMqbVm6sx3Z0R++gSiBlgMv6yUi2q1DeGFKQgE=
cloud.google.com/go/storage v1.22.1 h1:F6IlQJZrZM++apn9V5/VfS3gbTUYg98PS3EMQAzqtfg=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
@ -125,8 +124,6 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 h1:R/qAiUxFT3mNgQaNqJe0IVznjKRNm23ohAIh9lgtlzc=
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0/go.mod h1:v3ZDlfVAL1OrkKHbGSFFK60k0/7hruHPDq2XMs9Gu6U=
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@ -145,8 +142,8 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.35.31/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.44.18 h1:rPDxVLNZL9R76yifC0kYOnfnkMswLfy89c8LBJSyvgY=
github.com/aws/aws-sdk-go v1.44.18/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.44.22 h1:StP+vxaFzl445mSML6KzgiTcqpA+eVwbO5fMNvhVN7c=
github.com/aws/aws-sdk-go v1.44.22/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@ -438,9 +435,8 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -819,8 +815,8 @@ github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.7.1 h1:DsAOFeI9T0vmUW4LiGR5mhuCIn5kqGIE4WMU2ytmH00=
github.com/urfave/cli/v2 v2.7.1/go.mod h1:TYFbtzt/azQoJOrGH5mDfZtS0jIkl/OeFwlRWPR9KRM=
github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4=
github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
@ -844,6 +840,8 @@ github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHM
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg=
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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -994,8 +992,9 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220524220425-1d687d428aca h1:xTaFYiPROfpPhqrfTIDXj0ri1SpfueYT951s4bAuDO8=
golang.org/x/net v0.0.0-20220524220425-1d687d428aca/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1014,8 +1013,9 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw=
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1122,8 +1122,8 @@ golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220519141025-dcacdad47464 h1:MpIuURY70f0iKp/oooEFtB2oENcHITo/z1b6u41pKCw=
golang.org/x/sys v0.0.0-20220519141025-dcacdad47464/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1265,10 +1265,10 @@ google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/S
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
google.golang.org/api v0.80.0 h1:IQWaGVCYnsm4MO3hh+WtSXMzMzuyFx/fuR8qkN3A0Qo=
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/api v0.81.0 h1:o8WF5AvfidafWbFjsRyupxyEQJNUWxLZJCK5NXrxZZ8=
google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1349,17 +1349,17 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220405205423-9d709892a2bf/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220525015930-6ca3db687a9d h1:8BnRR08DxAQ+e2pFx64Q3Ltg/AkrrxyG1LLa1WpomyA=
google.golang.org/genproto v0.0.0-20220525015930-6ca3db687a9d/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=

View file

@ -1,18 +1,18 @@
{
"accessapproval": "1.2.0",
"accessapproval": "1.3.0",
"accesscontextmanager": "1.2.0",
"aiplatform": "1.9.0",
"analytics": "0.6.0",
"aiplatform": "1.10.0",
"analytics": "0.6.1",
"apigateway": "1.2.0",
"apigeeconnect": "1.2.0",
"appengine": "1.2.0",
"appengine": "1.3.0",
"area120": "0.3.0",
"artifactregistry": "1.3.0",
"asset": "1.2.0",
"assuredworkloads": "0.5.0",
"assuredworkloads": "0.6.0",
"automl": "1.3.0",
"billing": "1.2.0",
"binaryauthorization": "0.4.0",
"binaryauthorization": "0.5.0",
"certificatemanager": "0.2.0",
"channel": "1.6.0",
"cloudbuild": "1.2.0",
@ -29,23 +29,25 @@
"dataplex": "0.4.0",
"dataproc": "1.5.0",
"dataqna": "0.3.0",
"datastream": "0.3.0",
"datastream": "0.5.0",
"deploy": "1.2.0",
"dialogflow": "1.8.1",
"dialogflow": "1.9.0",
"dlp": "1.4.0",
"documentai": "1.4.0",
"domains": "0.4.0",
"essentialcontacts": "1.2.0",
"eventarc": "1.5.0",
"eventarc": "1.6.0",
"filestore": "1.2.0",
"functions": "1.3.0",
"gaming": "1.2.0",
"gkebackup": "0.1.0",
"gkeconnect": "0.3.0",
"gkehub": "0.5.0",
"gkemulticloud": "0.2.0",
"grafeas": "0.2.0",
"gsuiteaddons": "1.2.0",
"iam": "0.3.0",
"iap": "1.2.0",
"iap": "1.3.0",
"ids": "0.3.0",
"iot": "1.2.0",
"kms": "1.4.0",
@ -59,7 +61,7 @@
"networkconnectivity": "1.2.0",
"networkmanagement": "1.2.0",
"networksecurity": "0.3.0",
"notebooks": "0.3.0",
"notebooks": "0.4.0",
"optimization": "0.1.0",
"orchestration": "1.2.0",
"orgpolicy": "1.3.0",
@ -68,24 +70,24 @@
"phishingprotection": "0.3.0",
"policytroubleshooter": "1.2.0",
"privatecatalog": "0.3.0",
"recaptchaenterprise": "1.3.1",
"recaptchaenterprise/v2": "2.0.0",
"recommendationengine": "0.2.0",
"recommender": "1.3.0",
"redis": "1.5.0",
"resourcemanager": "1.2.0",
"resourcesettings": "1.2.0",
"retail": "1.2.0",
"run": "0.1.0",
"retail": "1.3.0",
"run": "0.1.1",
"scheduler": "1.2.0",
"secretmanager": "1.4.0",
"security": "1.3.0",
"security": "1.4.0",
"securitycenter": "1.7.0",
"servicecontrol": "1.3.0",
"servicedirectory": "1.2.0",
"servicemanagement": "1.3.0",
"serviceusage": "1.2.0",
"shell": "1.2.0",
"speech": "1.3.1",
"speech": "1.4.0",
"storagetransfer": "1.3.0",
"talent": "0.5.0",
"texttospeech": "1.3.0",
@ -94,10 +96,10 @@
"translate": "1.2.0",
"video": "1.4.0",
"videointelligence": "1.2.0",
"vision": "1.2.0",
"vision/v2": "2.0.0",
"vmmigration": "0.3.0",
"vpcaccess": "1.2.0",
"webrisk": "1.2.0",
"websecurityscanner": "1.2.0",
"workflows": "1.3.0"
"workflows": "1.4.0"
}

View file

@ -1,3 +1,3 @@
{
".": "0.101.1"
".": "0.102.0"
}

View file

@ -1,5 +1,12 @@
# Changes
## [0.102.0](https://github.com/googleapis/google-cloud-go/compare/v0.101.1...v0.102.0) (2022-05-24)
### Features
* **civil:** add Before and After methods to civil.Time ([#5703](https://github.com/googleapis/google-cloud-go/issues/5703)) ([7acaaaf](https://github.com/googleapis/google-cloud-go/commit/7acaaafef47668c3e8382b8bc03475598c3db187))
### [0.101.1](https://github.com/googleapis/google-cloud-go/compare/v0.101.0...v0.101.1) (2022-05-03)

File diff suppressed because it is too large Load diff

View file

@ -126,12 +126,18 @@
"gaming": {
"component": "gaming"
},
"gkebackup": {
"component": "gkebackup"
},
"gkeconnect": {
"component": "gkeconnect"
},
"gkehub": {
"component": "gkehub"
},
"gkemulticloud": {
"component": "gkemulticloud"
},
"grafeas": {
"component": "grafeas"
},
@ -210,7 +216,7 @@
"privatecatalog": {
"component": "privatecatalog"
},
"recaptchaenterprise": {
"recaptchaenterprise/v2": {
"component": "recaptchaenterprise"
},
"recommendationengine": {
@ -288,7 +294,7 @@
"videointelligence": {
"component": "videointelligence"
},
"vision": {
"vision/v2": {
"component": "vision"
},
"vmmigration": {

View file

@ -1,19 +0,0 @@
Matchr: an approximate string matching library for the Go programming language
Copyright (C) 2013-2014 Ant Zucaro
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
You can contact Ant Zucaro at azucaro at gmail dot com.

View file

@ -1,12 +0,0 @@
# matchr
An approximate string matching library for the [Go programming language](http://www.golang.org).
## Rationale
Data used in record linkage can often be of dubious quality. Typographical
errors or changing data elements (to name a few things) make establishing similarity between two sets of data
difficult. Rather than use exact string comparison in such situations, it is
vital to have a means to identify how similar two strings are. Similarity functions can cater
to certain data sets in order to make better matching decisions. The matchr library provides
several of these similarity functions.

View file

@ -1,112 +0,0 @@
package matchr
// DamerauLevenshtein computes the Damerau-Levenshtein distance between two
// strings. The returned value - distance - is the number of insertions,
// deletions, substitutions, and transpositions it takes to transform one
// string (s1) into another (s2). Each step in the transformation "costs"
// one distance point. It is similar to the Optimal String Alignment,
// algorithm, but is more complex because it allows multiple edits on
// substrings.
//
// This implementation is based off of the one found on Wikipedia at
// http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Distance_with_adjacent_transpositions
// as well as KevinStern's Java implementation found at
// https://github.com/KevinStern/software-and-algorithms.
func DamerauLevenshtein(s1 string, s2 string) (distance int) {
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
// the maximum possible distance
inf := len(r1) + len(r2)
// if one string is blank, we needs insertions
// for all characters in the other one
if len(r1) == 0 {
return len(r2)
}
if len(r2) == 0 {
return len(r1)
}
// construct the edit-tracking matrix
matrix := make([][]int, len(r1))
for i := range matrix {
matrix[i] = make([]int, len(r2))
}
// seen characters
seenRunes := make(map[rune]int)
if r1[0] != r2[0] {
matrix[0][0] = 1
}
seenRunes[r1[0]] = 0
for i := 1; i < len(r1); i++ {
deleteDist := matrix[i-1][0] + 1
insertDist := (i+1)*1 + 1
var matchDist int
if r1[i] == r2[0] {
matchDist = i
} else {
matchDist = i + 1
}
matrix[i][0] = min(min(deleteDist, insertDist), matchDist)
}
for j := 1; j < len(r2); j++ {
deleteDist := (j + 1) * 2
insertDist := matrix[0][j-1] + 1
var matchDist int
if r1[0] == r2[j] {
matchDist = j
} else {
matchDist = j + 1
}
matrix[0][j] = min(min(deleteDist, insertDist), matchDist)
}
for i := 1; i < len(r1); i++ {
var maxSrcMatchIndex int
if r1[i] == r2[0] {
maxSrcMatchIndex = 0
} else {
maxSrcMatchIndex = -1
}
for j := 1; j < len(r2); j++ {
swapIndex, ok := seenRunes[r2[j]]
jSwap := maxSrcMatchIndex
deleteDist := matrix[i-1][j] + 1
insertDist := matrix[i][j-1] + 1
matchDist := matrix[i-1][j-1]
if r1[i] != r2[j] {
matchDist += 1
} else {
maxSrcMatchIndex = j
}
// for transpositions
var swapDist int
if ok && jSwap != -1 {
iSwap := swapIndex
var preSwapCost int
if iSwap == 0 && jSwap == 0 {
preSwapCost = 0
} else {
preSwapCost = matrix[maxI(0, iSwap-1)][maxI(0, jSwap-1)]
}
swapDist = i + j + preSwapCost - iSwap - jSwap - 1
} else {
swapDist = inf
}
matrix[i][j] = min(min(min(deleteDist, insertDist), matchDist), swapDist)
}
seenRunes[r1[i]] = i
}
return matrix[len(r1)-1][len(r2)-1]
}

View file

@ -1,25 +0,0 @@
package matchr
import "errors"
// Hamming computes the Hamming distance between two equal-length strings.
// This is the number of times the two strings differ between characters at
// the same index. This implementation is based off of the algorithm
// description found at http://en.wikipedia.org/wiki/Hamming_distance.
func Hamming(s1 string, s2 string) (distance int, err error) {
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
if len(r1) != len(r2) {
err = errors.New("Hamming distance of different sized strings.")
return
}
for i, v := range r1 {
if r2[i] != v {
distance += 1
}
}
return
}

View file

@ -1,135 +0,0 @@
package matchr
func jaroWinklerBase(s1 string, s2 string,
longTolerance bool, winklerize bool) (distance float64) {
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
r1Length := len(r1)
r2Length := len(r2)
if r1Length == 0 || r2Length == 0 {
return
}
minLength := 0
if r1Length > r2Length {
minLength = r1Length
} else {
minLength = r2Length
}
searchRange := minLength
searchRange = (searchRange / 2) - 1
if searchRange < 0 {
searchRange = 0
}
var lowLim, hiLim, transCount, commonChars int
var i, j, k int
r1Flag := make([]bool, r1Length+1)
r2Flag := make([]bool, r2Length+1)
// find the common chars within the acceptable range
commonChars = 0
for i, _ = range r1 {
if i >= searchRange {
lowLim = i - searchRange
} else {
lowLim = 0
}
if (i + searchRange) <= (r2Length - 1) {
hiLim = i + searchRange
} else {
hiLim = r2Length - 1
}
for j := lowLim; j <= hiLim; j++ {
if !r2Flag[j] && r2[j] == r1[i] {
r2Flag[j] = true
r1Flag[i] = true
commonChars++
break
}
}
}
// if we have nothing in common at this point, nothing else can be done
if commonChars == 0 {
return
}
// otherwise we count the transpositions
k = 0
transCount = 0
for i, _ := range r1 {
if r1Flag[i] {
for j = k; j < r2Length; j++ {
if r2Flag[j] {
k = j + 1
break
}
}
if r1[i] != r2[j] {
transCount++
}
}
}
transCount /= 2
// adjust for similarities in nonmatched characters
distance = float64(commonChars)/float64(r1Length) +
float64(commonChars)/float64(r2Length) +
(float64(commonChars-transCount))/float64(commonChars)
distance /= 3.0
// give more weight to already-similar strings
if winklerize && distance > 0.7 {
// the first 4 characters in common
if minLength >= 4 {
j = 4
} else {
j = minLength
}
for i = 0; i < j && len(r1) > i && len(r2) > i && r1[i] == r2[i] && nan(r1[i]); i++ {
}
if i > 0 {
distance += float64(i) * 0.1 * (1.0 - distance)
}
if longTolerance && (minLength > 4) && (commonChars > i+1) &&
(2*commonChars >= minLength+i) {
if nan(r1[0]) {
distance += (1.0 - distance) * (float64(commonChars-i-1) /
(float64(r1Length) + float64(r2Length) - float64(i*2) + 2))
}
}
}
return
}
// Jaro computes the Jaro edit distance between two strings. It represents
// this with a float64 between 0 and 1 inclusive, with 0 indicating the two
// strings are not at all similar and 1 indicating the two strings are exact
// matches.
//
// See http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance for a
// full description.
func Jaro(r1 string, r2 string) (distance float64) {
return jaroWinklerBase(r1, r2, false, false)
}
// JaroWinkler computes the Jaro-Winkler edit distance between two strings.
// This is a modification of the Jaro algorithm that gives additional weight
// to prefix matches.
func JaroWinkler(r1 string, r2 string, longTolerance bool) (distance float64) {
return jaroWinklerBase(r1, r2, longTolerance, true)
}

View file

@ -1,48 +0,0 @@
package matchr
// Levenshtein computes the Levenshtein distance between two
// strings. The returned value - distance - is the number of insertions,
// deletions, and substitutions it takes to transform one
// string (s1) into another (s2). Each step in the transformation "costs"
// one distance point.
func Levenshtein(s1 string, s2 string) (distance int) {
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
rows := len(r1) + 1
cols := len(r2) + 1
var d1 int
var d2 int
var d3 int
var i int
var j int
dist := make([]int, rows*cols)
for i = 0; i < rows; i++ {
dist[i*cols] = i
}
for j = 0; j < cols; j++ {
dist[j] = j
}
for j = 1; j < cols; j++ {
for i = 1; i < rows; i++ {
if r1[i-1] == r2[j-1] {
dist[(i*cols)+j] = dist[((i-1)*cols)+(j-1)]
} else {
d1 = dist[((i-1)*cols)+j] + 1
d2 = dist[(i*cols)+(j-1)] + 1
d3 = dist[((i-1)*cols)+(j-1)] + 1
dist[(i*cols)+j] = min(d1, min(d2, d3))
}
}
}
distance = dist[(cols*rows)-1]
return
}

View file

@ -1,30 +0,0 @@
package matchr
// LongestCommonSubsequence computes the longest substring
// between two strings. The returned value is the length
// of the substring, which contains letters from both
// strings, while maintaining the order of the letters.
func LongestCommonSubsequence(s1, s2 string) int {
r1 := []rune(s1)
r2 := []rune(s2)
table := make([][]int, len(s1)+1)
// Construct 2D table
for i := range table {
table[i] = make([]int, len(s2)+1)
}
var i int
var j int
for i = len(r1) - 1; i >= 0; i-- {
for j = len(r2) - 1; j >= 0; j-- {
if r1[i] == r2[j] {
table[i][j] = 1 + table[i+1][j+1]
} else {
table[i][j] = maxI(table[i+1][j], table[i][j+1])
}
}
}
return table[0][0]
}

View file

@ -1,721 +0,0 @@
package matchr
import (
"bytes"
"strings"
)
type metaphoneresult struct {
// the maximum number of code values to calculate
maxLength int
// whether to calculate an alternate
calcAlternate bool
// no direct modifications - only through add()
primary bytes.Buffer
alternate bytes.Buffer
// length of the private buffers
PrimaryLength int
AlternateLength int
}
func newMetaphoneresult(maxLength int, calcAlternate bool) (r *metaphoneresult) {
r = &metaphoneresult{maxLength: maxLength, calcAlternate: calcAlternate}
return
}
func (r *metaphoneresult) add(c1 string, c2 string) {
if c1 != "" {
r.primary.WriteString(c1)
r.PrimaryLength += len(c1)
}
if c2 != "" && r.calcAlternate {
r.alternate.WriteString(c2)
r.AlternateLength += len(c2)
}
}
func (r *metaphoneresult) isComplete() bool {
return r.PrimaryLength >= r.maxLength && r.AlternateLength >= r.maxLength
}
func (r *metaphoneresult) result() (primary string, alternate string) {
primary = r.primary.String()
if len(primary) > r.maxLength {
primary = primary[0:r.maxLength]
}
alternate = r.alternate.String()
if len(alternate) > r.maxLength {
alternate = alternate[0:r.maxLength]
}
return
}
// utility functions for checking things within a string
func isSlavoGermanic(value string) bool {
return strings.Contains(value, "W") || strings.Contains(value, "K") ||
strings.Contains(value, "CZ") || strings.Contains(value, "WITZ")
}
func isSilentStart(input runestring) bool {
SILENT_START := [...]string{"GN", "KN", "PN", "WR", "PS"}
prefix := input.SafeSubstr(0, 2)
for _, criteria := range SILENT_START {
if prefix == criteria {
return true
}
}
return false
}
func handleVowel(result *metaphoneresult, index int) int {
if index == 0 {
result.add("A", "A")
}
return index + 1
}
/******************************************************************************
* Entry handlers for letters.
*****************************************************************************/
func handleC(input runestring, result *metaphoneresult, index int) int {
if conditionC0(input, index) {
result.add("K", "K")
index += 2
} else if index == 0 && input.Contains(index, 6, "CAESAR") {
result.add("S", "S")
index += 2
} else if input.Contains(index, 2, "CH") {
index = handleCH(input, result, index)
} else if input.Contains(index, 2, "CZ") &&
!input.Contains(index-2, 4, "WICZ") {
result.add("S", "X")
index += 2
} else if input.Contains(index+1, 3, "CIA") {
result.add("X", "X")
index += 3
} else if input.Contains(index, 2, "CC") &&
!(index == 1 && input.SafeAt(0) == 'M') {
return handleCC(input, result, index)
} else if input.Contains(index, 2, "CK") ||
input.Contains(index, 2, "CG") ||
input.Contains(index, 2, "CQ") {
result.add("K", "K")
index += 2
} else if input.Contains(index, 2, "CI") ||
input.Contains(index, 2, "CE") ||
input.Contains(index, 2, "CY") {
if input.Contains(index, 3, "CIO") ||
input.Contains(index, 3, "CIE") ||
input.Contains(index, 3, "CIA") {
result.add("S", "X")
} else {
result.add("S", "S")
}
index += 2
} else {
result.add("K", "K")
if input.Contains(index+1, 2, " C") ||
input.Contains(index+1, 2, " Q") ||
input.Contains(index+1, 2, " G") {
index += 3
} else if (input.Contains(index+1, 1, "C") ||
input.Contains(index+1, 1, "K") ||
input.Contains(index+1, 1, "Q")) &&
!(input.Contains(index+1, 2, "CE") ||
input.Contains(index+1, 2, "CI")) {
index += 2
} else {
index++
}
}
return index
}
func handleCC(input runestring, result *metaphoneresult, index int) int {
if input.Contains(index+2, 1, "I", "E", "H") &&
!input.Contains(index+2, 2, "HU") {
if (index == 1 && input.SafeAt(index-1) == 'A') ||
(input.Contains(index-1, 5, "UCCEE", "UCCES")) {
result.add("KS", "KS")
} else {
result.add("X", "X")
}
index += 3
} else {
result.add("K", "K")
index += 2
}
return index
}
func handleCH(input runestring, result *metaphoneresult, index int) int {
if index > 0 && input.Contains(index, 4, "CHAE") {
result.add("K", "X")
return index + 2
} else if conditionCH0(input, index) {
result.add("K", "K")
return index + 2
// TODO: combine this condition with the one above?
} else if conditionCH1(input, index) {
result.add("K", "K")
return index + 2
} else {
if index > 0 {
if input.Contains(0, 2, "MC") {
result.add("K", "K")
} else {
result.add("X", "K")
}
} else {
result.add("X", "X")
}
return index + 2
}
}
func handleD(input runestring, result *metaphoneresult, index int) int {
if input.Contains(index, 2, "DG") {
if input.Contains(index+2, 1, "I", "E", "Y") {
result.add("J", "J")
index += 3
} else {
result.add("TK", "TK")
index += 2
}
} else if input.Contains(index, 2, "DT", "DD") {
result.add("T", "T")
index += 2
} else {
result.add("T", "T")
index++
}
return index
}
func handleG(input runestring, result *metaphoneresult, index int, slavoGermanic bool) int {
if input.SafeAt(index+1) == 'H' {
index = handleGH(input, result, index)
} else if input.SafeAt(index+1) == 'N' {
if index == 1 && isVowel(input.SafeAt(0)) && !slavoGermanic {
result.add("KN", "N")
} else if !input.Contains(index+2, 2, "EY") && input.SafeAt(index+1) != 'Y' && !slavoGermanic {
result.add("N", "KN")
} else {
result.add("KN", "KN")
}
index += 2
} else if input.Contains(index+1, 2, "LI") && !slavoGermanic {
result.add("KL", "L")
index += 2
} else if index == 0 && (input.SafeAt(index+1) == 'Y' ||
input.Contains(index+1, 2, "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER")) {
result.add("K", "J")
index += 2
} else if (input.Contains(index+1, 2, "ER") ||
input.SafeAt(index+1) == 'Y') &&
!input.Contains(0, 6, "DANGER", "RANGER", "MANGER") &&
!input.Contains(index-1, 1, "E", "I") &&
!input.Contains(index-1, 3, "RGY", "OGY") {
result.add("K", "J")
index += 2
} else if input.Contains(index+1, 1, "E", "I", "Y") ||
input.Contains(index-1, 4, "AGGI", "OGGI") {
if input.Contains(0, 4, "VAN ", "VON ") ||
input.Contains(0, 3, "SCH") ||
input.Contains(index+1, 2, "ET") {
result.add("K", "K")
} else if input.Contains(index+1, 3, "IER") {
result.add("J", "J")
} else {
result.add("J", "K")
}
index += 2
} else if input.SafeAt(index+1) == 'G' {
result.add("K", "K")
index += 2
} else {
result.add("K", "K")
index++
}
return index
}
func handleGH(input runestring, result *metaphoneresult, index int) int {
if index > 0 && !isVowel(input.SafeAt(index-1)) {
result.add("K", "K")
index += 2
} else if index == 0 {
if input.SafeAt(index+2) == 'I' {
result.add("J", "J")
} else {
result.add("K", "K")
}
index += 2
} else if (index > 1 && input.Contains(index-2, 1, "B", "H", "D")) ||
(index > 2 && input.Contains(index-3, 1, "B", "H", "D")) ||
(index > 3 && input.Contains(index-4, 1, "B", "H")) {
index += 2
} else {
if index > 2 && input.SafeAt(index-1) == 'U' &&
input.Contains(index-3, 1, "C", "G", "L", "R", "T") {
result.add("F", "F")
} else if index > 0 && input.SafeAt(index-1) != 'I' {
result.add("K", "K")
}
index += 2
}
return index
}
func handleH(input runestring, result *metaphoneresult, index int) int {
if (index == 0 || isVowel(input.SafeAt(index-1))) &&
isVowel(input.SafeAt(index+1)) {
result.add("H", "H")
index += 2
} else {
index++
}
return index
}
func handleJ(input runestring, result *metaphoneresult, index int, slavoGermanic bool) int {
if input.Contains(index, 4, "JOSE") || input.Contains(0, 4, "SAN ") {
if (index == 0 && (input.SafeAt(index+4) == ' ') ||
len(input) == 4) || input.Contains(0, 4, "SAN ") {
result.add("H", "H")
} else {
result.add("J", "H")
}
index++
} else {
if index == 0 && !input.Contains(index, 4, "JOSE") {
result.add("J", "A")
} else if isVowel(input.SafeAt(index-1)) && !slavoGermanic &&
(input.SafeAt(index+1) == 'A' || input.SafeAt(index+1) == 'O') {
result.add("J", "H")
} else if index == (len(input) - 1) {
result.add("J", " ")
} else if !input.Contains(index+1, 1,
"L", "T", "K", "S", "N", "M", "B", "Z") &&
!input.Contains(index-1, 1, "S", "K", "L") {
result.add("J", "J")
}
if input.SafeAt(index+1) == 'J' {
index += 2
} else {
index++
}
}
return index
}
func handleL(input runestring, result *metaphoneresult, index int) int {
if input.SafeAt(index+1) == 'L' {
if conditionL0(input, index) {
result.add("L", "")
} else {
result.add("L", "L")
}
index += 2
} else {
result.add("L", "L")
index++
}
return index
}
func handleP(input runestring, result *metaphoneresult, index int) int {
if input.SafeAt(index+1) == 'H' {
result.add("F", "F")
index += 2
} else {
result.add("P", "P")
if input.Contains(index+1, 1, "P", "B") {
index += 2
} else {
index++
}
}
return index
}
func handleR(input runestring, result *metaphoneresult, index int, slavoGermanic bool) int {
if index == (len(input)-1) && !slavoGermanic &&
input.Contains(index-2, 2, "IE") &&
!input.Contains(index-4, 2, "ME", "MA") {
result.add("", "R")
} else {
result.add("R", "R")
}
if input.SafeAt(index+1) == 'R' {
index += 2
} else {
index++
}
return index
}
func handleS(input runestring, result *metaphoneresult, index int, slavoGermanic bool) int {
if input.Contains(index-1, 3, "ISL", "YSL") {
index++
} else if index == 0 && input.Contains(index, 5, "SUGAR") {
result.add("X", "S")
index++
} else if input.Contains(index, 2, "SH") {
if input.Contains(index+1, 4, "HEIM", "HOEK", "HOLM", "HOLZ") {
result.add("S", "S")
} else {
result.add("X", "X")
}
index += 2
} else if input.Contains(index, 3, "SIO", "SIA") ||
input.Contains(index, 4, "SIAN") {
if slavoGermanic {
result.add("S", "S")
} else {
result.add("S", "X")
}
index += 3
} else if (index == 0 && input.Contains(index+1, 1, "M", "N", "L", "W")) ||
input.Contains(index+1, 1, "Z") {
result.add("S", "X")
if input.Contains(index+1, 1, "Z") {
index += 2
} else {
index++
}
} else if input.Contains(index, 2, "SC") {
index = handleSC(input, result, index)
} else {
if index == len(input)-1 &&
input.Contains(index-2, 2, "AI", "OI") {
result.add("", "S")
} else {
result.add("S", "S")
}
if input.Contains(index+1, 1, "S", "Z") {
index += 2
} else {
index++
}
}
return index
}
func handleSC(input runestring, result *metaphoneresult, index int) int {
if input.SafeAt(index+2) == 'H' {
if input.Contains(index+3, 2, "OO", "ER", "EN", "UY", "ED", "EM") {
if input.Contains(index+3, 2, "ER", "EN") {
result.add("X", "SK")
} else {
result.add("SK", "SK")
}
} else {
if index == 0 && !isVowel(input.SafeAt(3)) && input.SafeAt(3) != 'W' {
result.add("X", "S")
} else {
result.add("X", "X")
}
}
} else if input.Contains(index+2, 1, "I", "E", "Y") {
result.add("S", "S")
} else {
result.add("SK", "SK")
}
index += 3
return index
}
func handleT(input runestring, result *metaphoneresult, index int) int {
if input.Contains(index, 4, "TION") {
result.add("X", "X")
index += 3
} else if input.Contains(index, 3, "TIA", "TCH") {
result.add("X", "X")
index += 3
} else if input.Contains(index, 2, "TH") || input.Contains(index, 3, "TTH") {
if input.Contains(index+2, 2, "OM", "AM") ||
input.Contains(0, 4, "VAN ", "VON ") ||
input.Contains(0, 3, "SCH") {
result.add("T", "T")
} else {
result.add("0", "T")
}
index += 2
} else {
result.add("T", "T")
if input.Contains(index+1, 1, "T", "D") {
index += 2
} else {
index++
}
}
return index
}
func handleW(input runestring, result *metaphoneresult, index int) int {
if input.Contains(index, 2, "WR") {
result.add("R", "R")
index += 2
} else {
if index == 0 && (isVowel(input.SafeAt(index+1)) ||
input.Contains(index, 2, "WH")) {
if isVowel(input.SafeAt(index + 1)) {
result.add("A", "F")
} else {
result.add("A", "A")
}
index++
} else if (index == len(input)-1 && isVowel(input.SafeAt(index-1))) ||
input.Contains(index-1, 5, "EWSKI", "EWSKY", "OWSKI", "OWSKY") ||
input.Contains(0, 3, "SCH") {
result.add("", "F")
index++
} else if input.Contains(index, 4, "WICZ", "WITZ") {
result.add("TS", "FX")
index += 4
} else {
index++
}
}
return index
}
func handleX(input runestring, result *metaphoneresult, index int) int {
if index == 0 {
result.add("S", "S")
index++
} else {
if !((index == len(input)-1) &&
(input.Contains(index-3, 3, "IAU", "EAU") ||
input.Contains(index-2, 2, "AU", "OU"))) {
result.add("KS", "KS")
}
if input.Contains(index+1, 1, "C", "X") {
index += 2
} else {
index++
}
}
return index
}
func handleZ(input runestring, result *metaphoneresult, index int, slavoGermanic bool) int {
if input.SafeAt(index+1) == 'H' {
result.add("J", "J")
} else {
if input.Contains(index+1, 2, "ZO", "ZI", "ZA") ||
(slavoGermanic && (index > 0 && input.SafeAt(index-1) != 'T')) {
result.add("S", "TS")
} else {
result.add("S", "S")
}
}
if input.SafeAt(index+1) == 'Z' {
index += 2
} else {
index++
}
return index
}
/******************************************************************************
* Complex conditional handlers for letters
*****************************************************************************/
func conditionC0(input runestring, index int) bool {
if input.Contains(index, 4, "CHIA") {
return true
} else if index <= 1 {
return false
} else if isVowel(input.SafeAt(index - 2)) {
return false
} else if !input.Contains(index-1, 3, "ACH") {
return false
} else {
c := input.SafeAt(index + 2)
return (c != 'I' && c != 'E') ||
(input.Contains(index-2, 6, "BACHER") ||
input.Contains(index-2, 6, "MACHER"))
}
}
func conditionCH0(input runestring, index int) bool {
if index != 0 {
return false
} else if !input.Contains(index+1, 5, "HARAC", "HARIS") &&
!input.Contains(index+1, 3, "HOR", "HYM", "HIA", "HEM") {
return false
} else if input.Contains(0, 5, "CHORE") {
return false
} else {
return true
}
}
func conditionCH1(input runestring, index int) bool {
// good god this is ugly
return (input.Contains(0, 4, "VAN ", "VON ") || input.Contains(0, 3, "SCH")) ||
input.Contains(index-2, 6, "ORCHES", "ARCHIT", "ORCHID") ||
input.Contains(index+2, 1, "T", "S") ||
((input.Contains(index-1, 1, "A", "O", "U", "E") || index == 0) &&
(input.Contains(index+2, 1, "L", "R", "N", "M", "B", "H", "F", "V", "W", " ") ||
index+1 == len(input)-1))
}
func conditionL0(input runestring, index int) bool {
if index == (len(input)-3) &&
input.Contains(index-1, 4, "ILLO", "ILLA", "ALLE") {
return true
} else if (input.Contains(len(input)-2, 2, "AS", "OS") ||
input.Contains(len(input)-1, 1, "A", "O")) &&
(input.Contains(index-1, 4, "ALLE")) {
return true
} else {
return false
}
}
func conditionM0(input runestring, index int) bool {
if input.SafeAt(index+1) == 'M' {
return true
}
return input.Contains(index-1, 3, "UMB") &&
((index+1) == (len(input)-1) ||
input.Contains(index+2, 2, "ER"))
}
// DoubleMetaphone computes the Double-Metaphone value of the input string.
// This value is a phonetic representation of how the string sounds, with
// affordances for many different language dialects. It was originally
// developed by Lawrence Phillips in the 1990s.
//
// More information about this algorithm can be found on Wikipedia at
// http://en.wikipedia.org/wiki/Metaphone.
func DoubleMetaphone(s1 string) (string, string) {
// trim, upper space
s1 = cleanInput(s1)
// structure to traverse the string by code point, not byte
input := runestring(s1)
slavoGermanic := isSlavoGermanic(s1)
// where we are in the string
index := 0
if isSilentStart(input) {
index += 1
}
result := newMetaphoneresult(4, true)
for !result.isComplete() && index <= len(input)-1 {
c := rune(input.SafeAt(index))
switch c {
case 'A', 'E', 'I', 'O', 'U', 'Y':
index = handleVowel(result, index)
case 'B':
result.add("P", "P")
if input.SafeAt(index+1) == 'B' {
index += 2
} else {
index++
}
case 'Ç':
result.add("S", "S")
index++
case 'C':
index = handleC(input, result, index)
case 'D':
index = handleD(input, result, index)
case 'F':
result.add("F", "F")
if input.SafeAt(index+1) == 'F' {
index += 2
} else {
index++
}
case 'G':
index = handleG(input, result, index, slavoGermanic)
case 'H':
index = handleH(input, result, index)
case 'J':
index = handleJ(input, result, index, slavoGermanic)
case 'K':
result.add("K", "K")
if input.SafeAt(index+1) == 'K' {
index += 2
} else {
index++
}
case 'L':
index = handleL(input, result, index)
case 'M':
result.add("M", "M")
if conditionM0(input, index) {
index += 2
} else {
index++
}
case 'N':
result.add("N", "N")
if input.SafeAt(index+1) == 'N' {
index += 2
} else {
index++
}
case 'Ñ':
result.add("N", "N")
index++
case 'P':
index = handleP(input, result, index)
case 'Q':
result.add("K", "K")
if input.SafeAt(index+1) == 'Q' {
index += 2
} else {
index++
}
case 'R':
index = handleR(input, result, index, slavoGermanic)
case 'S':
index = handleS(input, result, index, slavoGermanic)
case 'T':
index = handleT(input, result, index)
case 'V':
result.add("F", "F")
if input.SafeAt(index+1) == 'V' {
index += 2
} else {
index++
}
case 'W':
index = handleW(input, result, index)
case 'X':
index = handleX(input, result, index)
case 'Z':
index = handleZ(input, result, index, slavoGermanic)
default:
index++
}
}
return result.result()
}

View file

@ -1,156 +0,0 @@
package matchr
// NYSIIS computes the NYSIIS phonetic encoding of the input string. It is a
// modification of the traditional Soundex algorithm.
func NYSIIS(s1 string) string {
cleans1 := runestring(cleanInput(s1))
input := runestring(make([]rune, 0, len(s1)))
// The output can't be larger than the string itself
output := runestring(make([]rune, 0, len(s1)))
// 0. Remove all non-ASCII characters
for _, v := range cleans1 {
if v >= 65 && v <= 90 {
input = append(input, v)
}
}
if len(input) == 0 {
return ""
}
// 1. Transcoding first characters
switch input[0] {
case 'M':
if input.SafeSubstr(0, 3) == "MAC" {
// MAC -> MCC
input[1] = 'C'
}
case 'K':
if input.SafeSubstr(0, 2) == "KN" {
// KN -> NN
input[0] = 'N'
} else {
// K -> C
input[0] = 'C'
}
case 'P':
next := input.SafeAt(1)
if next == 'H' {
// PH -> FF
input[0] = 'F'
input[1] = 'F'
} else if next == 'F' {
// PF -> FF
input[0] = 'F'
}
case 'S':
if input.SafeSubstr(0, 3) == "SCH" {
input[1] = 'S'
input[2] = 'S'
}
}
// 2. Transcoding last characters
switch input.SafeSubstr(len(input)-2, 2) {
case "EE", "IE":
// EE, IE -> Y
input.Del(len(input) - 2)
input[len(input)-1] = 'Y'
case "DT", "RT", "RD", "NT", "ND":
// DT, RT, RD, NT, ND -> D
input.Del(len(input) - 2)
input[len(input)-1] = 'D'
}
// 3. First character of key = first character of name
output = append(output, input[0])
last := input[0]
for i := 1; i < len(input); i++ {
c := input[i]
switch c {
case 'A', 'I', 'O', 'U':
// A, E, I, O, U -> A (E is separate)
input[i] = 'A'
case 'E':
// EV -> AF, else A
if input.SafeAt(i+1) == 'V' {
input[i+1] = 'F'
}
input[i] = 'A'
case 'Q':
// Q -> G
input[i] = 'G'
case 'Z':
// Z -> S
input[i] = 'S'
case 'M':
// M -> N
input[i] = 'N'
case 'K':
// KN -> N, else K -> C
if input.SafeAt(i+1) == 'N' {
input.Del(i)
} else {
input[i] = 'C'
}
case 'S':
// SCH -> SSS
if input.SafeSubstr(i, 3) == "SCH" {
input[i+1] = 'S'
input[i+2] = 'S'
}
case 'P':
// PH -> FF
if input.SafeAt(i+1) == 'H' {
input[i] = 'F'
input[i+1] = 'F'
}
case 'H':
// H -> $(previous character) if previous character or
// next character is a non-vowel
prev := input.SafeAt(i - 1)
next := input.SafeAt(i + 1)
if !isVowelNoY(prev) || !isVowelNoY(next) {
input[i] = prev
}
case 'W':
prev := input.SafeAt(i - 1)
if isVowelNoY(prev) {
input[i] = prev
}
}
if input[i] != last && input[i] != 0 {
output = append(output, input[i])
}
last = input[i]
}
// have to be careful here because we've already added the first
// key value
if len(output) > 1 {
// remove trailing s
if output.SafeAt(len(output)-1) == 'S' {
output.Del(len(output) - 1)
}
// trailing AY -> Y
if len(output) > 2 && output.SafeSubstr(len(output)-2, 2) == "AY" {
output.Del(len(output) - 2)
}
// trailing A -> remove it
if output.SafeAt(len(output)-1) == 'A' {
output.Del(len(output) - 1)
}
}
if len(output) > 6 {
return string(output[0:6])
} else {
return string(output)
}
}

View file

@ -1,56 +0,0 @@
package matchr
// OSA computes the Optimal String Alignment distance between two
// strings. The returned value - distance - is the number of insertions,
// deletions, substitutions, and transpositions it takes to transform one
// string (s1) into another (s2). Each step in the transformation "costs"
// one distance point. It is similar to Damerau-Levenshtein, but is simpler
// because it does not allow multiple edits on any substring.
func OSA(s1 string, s2 string) (distance int) {
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
rows := len(r1) + 1
cols := len(r2) + 1
var i, j, d1, d2, d3, d_now, cost int
dist := make([]int, rows*cols)
for i = 0; i < rows; i++ {
dist[i*cols] = i
}
for j = 0; j < cols; j++ {
dist[j] = j
}
for i = 1; i < rows; i++ {
for j = 1; j < cols; j++ {
if r1[i-1] == r2[j-1] {
cost = 0
} else {
cost = 1
}
d1 = dist[((i-1)*cols)+j] + 1
d2 = dist[(i*cols)+(j-1)] + 1
d3 = dist[((i-1)*cols)+(j-1)] + cost
d_now = min(d1, min(d2, d3))
if i > 2 && j > 2 && r1[i-1] == r2[j-2] &&
r1[i-2] == r2[j-1] {
d1 = dist[((i-2)*cols)+(j-2)] + cost
d_now = min(d_now, d1)
}
dist[(i*cols)+j] = d_now
}
}
distance = dist[(cols*rows)-1]
return
}

View file

@ -1,128 +0,0 @@
package matchr
func preProcess(input []rune) []rune {
output := runestring(make([]rune, 0, len(input)))
// 0. Remove all non-ASCII characters
for _, v := range input {
if v >= 65 && v <= 90 {
output = append(output, v)
}
}
// 1. Remove all trailing 'S' characters at the end of the name
for i := len(output) - 1; i >= 0 && output[i] == 'S'; i-- {
output.Del(i)
}
// 2. Convert leading letter pairs as follows
// KN -> N, PH -> F, WR -> R
switch output.SafeSubstr(0, 2) {
case "KN":
output = output[1:]
case "PH":
output[0] = 'F' // H will be ignored anyway
case "WR":
output = output[1:]
}
// 3a. Convert leading single letters as follows:
// H -> Remove
if output.SafeAt(0) == 'H' {
output = output[1:]
}
// 3a. Convert leading single letters as follows:
// E,I,O,U,Y -> A
// P -> B
// V -> F
// K,Q -> C
// J -> G
// Z -> S
switch output.SafeAt(0) {
case 'E', 'I', 'O', 'U', 'Y':
output[0] = 'A'
case 'P':
output[0] = 'B'
case 'V':
output[0] = 'F'
case 'K', 'Q':
output[0] = 'C'
case 'J':
output[0] = 'G'
case 'Z':
output[0] = 'S'
}
return output
}
// Phonex computes the Phonex phonetic encoding of the input string. Phonex is
// a modification of the venerable Soundex algorithm. It accounts for a few
// more letter combinations to improve accuracy on some data sets.
//
// This implementation is based off of the original C implementation by the
// creator - A. J. Lait - as found in his research paper entitled "An
// Assessment of Name Matching Algorithms."
func Phonex(s1 string) string {
// preprocess
s1 = cleanInput(s1)
input := runestring(preProcess([]rune(s1)))
result := make([]rune, 0, len(input))
last := rune(0)
code := rune(0)
for i := 0; i < len(input) &&
input[i] != ' ' &&
input[i] != ',' &&
len(result) < 4; i++ {
switch input[i] {
case 'B', 'P', 'F', 'V':
code = '1'
case 'C', 'S', 'K', 'G', 'J', 'Q', 'X', 'Z':
code = '2'
case 'D', 'T':
if input.SafeAt(i+1) != 'C' {
code = '3'
}
case 'L':
if isVowel(input.SafeAt(i+1)) || i == len(input)-1 {
code = '4'
}
case 'M', 'N':
nextChar := input.SafeAt(i + 1)
if nextChar == 'D' || nextChar == 'G' {
// ignore next character
i++
}
code = '5'
case 'R':
if isVowel(input.SafeAt(i+1)) || i == len(input)-1 {
code = '6'
}
default:
code = 0
}
if last != code && code != 0 && i != 0 {
result = append(result, code)
}
// special case for 1st character: we use the actual character
if i == 0 {
result = append(result, input[i])
last = code
} else {
last = result[len(result)-1]
}
}
for len(result) < 4 {
result = append(result, '0')
}
return string(result)
}

View file

@ -1,44 +0,0 @@
package matchr
type runestring []rune
// A safe way to index a runestring. It will return a null rune if you try
// to index outside of the bounds of the runestring.
func (r *runestring) SafeAt(pos int) rune {
if pos < 0 || pos >= len(*r) {
return 0
} else {
return (*r)[pos]
}
}
// A safe way to obtain a substring of a runestring. It will return a null
// string ("") if you index somewhere outside its bounds.
func (r *runestring) SafeSubstr(pos int, length int) string {
if pos < 0 || pos > len(*r) || (pos+length) > len(*r) {
return ""
} else {
return string((*r)[pos : pos+length])
}
}
// Delete characters at positions pos. It will do nothing if you provide
// an index outside the bounds of the runestring.
func (r *runestring) Del(pos ...int) {
for _, i := range pos {
if i >= 0 && i <= len(*r) {
*r = append((*r)[:i], (*r)[i+1:]...)
}
}
}
// A helper to determine if any substrings exist within the given runestring.
func (r *runestring) Contains(start int, length int, criteria ...string) bool {
substring := r.SafeSubstr(start, length)
for _, c := range criteria {
if substring == c {
return true
}
}
return false
}

View file

@ -1,87 +0,0 @@
package matchr
const GAP_COST = float64(0.5)
func getCost(r1 []rune, r1Index int, r2 []rune, r2Index int) float64 {
if r1[r1Index] == r2[r2Index] {
return 1.0
} else {
return -2.0
}
}
// SmithWaterman computes the Smith-Waterman local sequence alignment for the
// two input strings. This was originally designed to find similar regions in
// strings representing DNA or protein sequences.
func SmithWaterman(s1 string, s2 string) float64 {
var cost float64
// index by code point, not byte
r1 := []rune(s1)
r2 := []rune(s2)
r1Len := len(r1)
r2Len := len(r2)
if r1Len == 0 {
return float64(r2Len)
}
if r2Len == 0 {
return float64(r1Len)
}
d := make([][]float64, r1Len)
for i := range d {
d[i] = make([]float64, r2Len)
}
var maxSoFar float64
for i := 0; i < r1Len; i++ {
// substitution cost
cost = getCost(r1, i, r2, 0)
if i == 0 {
d[0][0] = max(0.0, max(-GAP_COST, cost))
} else {
d[i][0] = max(0.0, max(d[i-1][0]-GAP_COST, cost))
}
// save if it is the biggest thus far
if d[i][0] > maxSoFar {
maxSoFar = d[i][0]
}
}
for j := 0; j < r2Len; j++ {
// substitution cost
cost = getCost(r1, 0, r2, j)
if j == 0 {
d[0][0] = max(0, max(-GAP_COST, cost))
} else {
d[0][j] = max(0, max(d[0][j-1]-GAP_COST, cost))
}
// save if it is the biggest thus far
if d[0][j] > maxSoFar {
maxSoFar = d[0][j]
}
}
for i := 1; i < r1Len; i++ {
for j := 1; j < r2Len; j++ {
cost = getCost(r1, i, r2, j)
// find the lowest cost
d[i][j] = max(
max(0, d[i-1][j]-GAP_COST),
max(d[i][j-1]-GAP_COST, d[i-1][j-1]+cost))
// save if it is the biggest thus far
if d[i][j] > maxSoFar {
maxSoFar = d[i][j]
}
}
}
return maxSoFar
}

View file

@ -1,72 +0,0 @@
package matchr
import "strings"
// Soundex computes the Soundex phonetic representation of the input string. It
// attempts to encode homophones with the same characters. More information can
// be found at http://en.wikipedia.org/wiki/Soundex.
func Soundex(s1 string) string {
if len(s1) == 0 {
return ""
}
// we should work with all uppercase
s1 = strings.ToUpper(s1)
input := NewString(s1)
// the encoded value
enc := input.Slice(0, 1)
c := ""
prev := ""
hw := false
for i := 0; i < input.RuneCount(); i++ {
switch rune(input.At(i)) {
case 'B', 'F', 'P', 'V':
c = "1"
case 'C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z':
c = "2"
case 'D', 'T':
c = "3"
case 'L':
c = "4"
case 'M', 'N':
c = "5"
case 'R':
c = "6"
case 'H', 'W':
hw = true
default:
c = ""
}
// don't encode the first position, but we need its code value
// to prevent repeats
if c != "" && c != prev && i > 0 {
// if the next encoded digit is different, we can add it right away
// if it is the same, though, it must not have been preceded
// by an 'H' or a 'W'
if enc[len(enc)-1:len(enc)] != c || !hw {
enc = enc + c
}
// we're done when we reach four encoded characters
if len(enc) == 4 {
break
}
}
prev = c
hw = false
}
// if we've fallen short of 4 "real" encoded characters,
// it gets padded with zeros
for len(enc) < 4 {
enc = enc + "0"
}
return enc
}

View file

@ -1,215 +0,0 @@
// 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 matchr
import (
"errors"
"unicode/utf8"
)
// String wraps a regular string with a small structure that provides more
// efficient indexing by code point index, as opposed to byte index.
// Scanning incrementally forwards or backwards is O(1) per index operation
// (although not as fast a range clause going forwards). Random access is
// O(N) in the length of the string, but the overhead is less than always
// scanning from the beginning.
// If the string is ASCII, random access is O(1).
// Unlike the built-in string type, String has internal mutable state and
// is not thread-safe.
type String struct {
str string
numRunes int
// If width > 0, the rune at runePos starts at bytePos and has the specified width.
width int
bytePos int
runePos int
nonASCII int // byte index of the first non-ASCII rune.
}
// NewString returns a new UTF-8 string with the provided contents.
func NewString(contents string) *String {
return new(String).Init(contents)
}
// Init initializes an existing String to hold the provided contents.
// It returns a pointer to the initialized String.
func (s *String) Init(contents string) *String {
s.str = contents
s.bytePos = 0
s.runePos = 0
for i := 0; i < len(contents); i++ {
if contents[i] >= utf8.RuneSelf {
// Not ASCII.
s.numRunes = utf8.RuneCountInString(contents)
_, s.width = utf8.DecodeRuneInString(contents)
s.nonASCII = i
return s
}
}
// ASCII is simple. Also, the empty string is ASCII.
s.numRunes = len(contents)
s.width = 0
s.nonASCII = len(contents)
return s
}
// String returns the contents of the String. This method also means the
// String is directly printable by fmt.Print.
func (s *String) String() string {
return s.str
}
// RuneCount returns the number of runes (Unicode code points) in the String.
func (s *String) RuneCount() int {
return s.numRunes
}
// IsASCII returns a boolean indicating whether the String contains only ASCII bytes.
func (s *String) IsASCII() bool {
return s.width == 0
}
// Slice returns the string sliced at rune positions [i:j].
func (s *String) Slice(i, j int) string {
// ASCII is easy. Let the compiler catch the indexing error if there is one.
if j < s.nonASCII {
return s.str[i:j]
}
if i < 0 || j > s.numRunes || i > j {
panic(errors.New("utf8.String: slice index out of range"))
}
if i == j {
return ""
}
// For non-ASCII, after At(i), bytePos is always the position of the indexed character.
var low, high int
switch {
case i < s.nonASCII:
low = i
case i == s.numRunes:
low = len(s.str)
default:
s.At(i)
low = s.bytePos
}
switch {
case j == s.numRunes:
high = len(s.str)
default:
s.At(j)
high = s.bytePos
}
return s.str[low:high]
}
// At returns the rune with index i in the String. The sequence of runes is the same
// as iterating over the contents with a "for range" clause.
func (s *String) At(i int) int {
// ASCII is easy. Let the compiler catch the indexing error if there is one.
if i < s.nonASCII {
return int(s.str[i])
}
// Now we do need to know the index is valid.
if i < 0 || i >= s.numRunes {
panic(errors.New("utf8.String: index out of range"))
}
var r rune
// Five easy common cases: within 1 spot of bytePos/runePos, or the beginning, or the end.
// With these cases, all scans from beginning or end work in O(1) time per rune.
switch {
case i == s.runePos-1: // backing up one rune
r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos])
s.runePos = i
s.bytePos -= s.width
return int(r)
case i == s.runePos+1: // moving ahead one rune
s.runePos = i
s.bytePos += s.width
fallthrough
case i == s.runePos:
r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:])
return int(r)
case i == 0: // start of string
r, s.width = utf8.DecodeRuneInString(s.str)
s.runePos = 0
s.bytePos = 0
return int(r)
case i == s.numRunes-1: // last rune in string
r, s.width = utf8.DecodeLastRuneInString(s.str)
s.runePos = i
s.bytePos = len(s.str) - s.width
return int(r)
}
// We need to do a linear scan. There are three places to start from:
// 1) The beginning
// 2) bytePos/runePos.
// 3) The end
// Choose the closest in rune count, scanning backwards if necessary.
forward := true
if i < s.runePos {
// Between beginning and pos. Which is closer?
// Since both i and runePos are guaranteed >= nonASCII, that's the
// lowest location we need to start from.
if i < (s.runePos-s.nonASCII)/2 {
// Scan forward from beginning
s.bytePos, s.runePos = s.nonASCII, s.nonASCII
} else {
// Scan backwards from where we are
forward = false
}
} else {
// Between pos and end. Which is closer?
if i-s.runePos < (s.numRunes-s.runePos)/2 {
// Scan forward from pos
} else {
// Scan backwards from end
s.bytePos, s.runePos = len(s.str), s.numRunes
forward = false
}
}
if forward {
// TODO: Is it much faster to use a range loop for this scan?
for {
r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:])
if s.runePos == i {
break
}
s.runePos++
s.bytePos += s.width
}
} else {
for {
r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos])
s.runePos--
s.bytePos -= s.width
if s.runePos == i {
break
}
}
}
return int(r)
}
// We want the panic in At(i) to satisfy os.Error, because that's what
// runtime panics satisfy, but we can't import os. This is our solution.
// error is the type of the error returned if a user calls String.At(i) with i out of range.
// It satisfies os.Error and runtime.Error.
// type error string
/*
func (err error) String() string {
return string(err)
}
func (err error) RunTimeError() {
}
*/

View file

@ -1,119 +0,0 @@
package matchr
import (
"math"
"strings"
)
// min of two integers
func min(a int, b int) (res int) {
if a < b {
res = a
} else {
res = b
}
return
}
// max of two integers
func maxI(a int, b int) (res int) {
if a < b {
res = b
} else {
res = a
}
return
}
// max of two float64s
func max(a float64, b float64) (res float64) {
if a < b {
res = b
} else {
res = a
}
return
}
// is this string index outside of the ASCII numeric code points?
func nan(c rune) bool {
return ((c > 57) || (c < 48))
}
// Round a float64 to the given precision
//
// http://play.golang.org/p/S654PxAe_N
//
// (via Rory McGuire at
// https://groups.google.com/forum/#!topic/golang-nuts/ITZV08gAugI)
func round(x float64, prec int) float64 {
if math.IsNaN(x) || math.IsInf(x, 0) {
return x
}
sign := 1.0
if x < 0 {
sign = -1
x *= -1
}
var rounder float64
pow := math.Pow(10, float64(prec))
intermed := x * pow
_, frac := math.Modf(intermed)
if frac >= 0.5 {
rounder = math.Ceil(intermed)
} else {
rounder = math.Floor(intermed)
}
return rounder / pow * sign
}
// A helper to determine if any substrings exist within the given string
func contains(value *String, start int, length int, criteria ...string) bool {
substring := substring(value, start, length)
for _, c := range criteria {
if substring == c {
return true
}
}
return false
}
// A fault-tolerant version of Slice. It will return nothing ("") if the index
// is out of bounds. This allows substring-ing without having to bound check
// every time.
func substring(value *String, start int, length int) string {
if start >= 0 && start+length <= value.RuneCount() {
return value.Slice(start, start+length)
} else {
return ""
}
}
func isVowel(c rune) bool {
switch c {
case 'A', 'E', 'I', 'O', 'U', 'Y':
return true
default:
return false
}
}
func isVowelNoY(c rune) bool {
switch c {
case 'A', 'E', 'I', 'O', 'U':
return true
default:
return false
}
}
func cleanInput(input string) string {
return strings.ToUpper(strings.TrimSpace(input))
}

View file

@ -8314,24 +8314,96 @@ var awsPartition = partition{
},
"email": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "email-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "email-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "email-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "email-fips.us-west-2.amazonaws.com",
},
},
},
"emr-containers": service{
@ -15421,6 +15493,9 @@ var awsPartition = partition{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{
@ -15586,6 +15661,25 @@ var awsPartition = partition{
}: endpoint{},
},
},
"proton": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"qldb": service{
Endpoints: serviceEndpoints{
endpointKey{
@ -22458,6 +22552,64 @@ var awsPartition = partition{
},
},
},
"wellarchitected": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"wisdom": service{
Endpoints: serviceEndpoints{
endpointKey{

View file

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.44.18"
const SDKVersion = "1.44.22"

View file

@ -55,11 +55,12 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be
reviewed and investigated and will result in a response that is deemed necessary
and appropriate to the circumstances. The project team is obligated to maintain
confidentiality with regard to the reporter of an incident. Further details of
specific enforcement policies may be posted separately.
reported by contacting urfave-governance@googlegroups.com, a members-only group
that is world-postable. All complaints will be reviewed and investigated and
will result in a response that is deemed necessary and appropriate to the
circumstances. The project team is obligated to maintain confidentiality with
regard to the reporter of an incident. Further details of specific enforcement
policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other

View file

@ -1,5 +1,4 @@
cli
===
# cli
[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://pkg.go.dev/github.com/urfave/cli/v2)
[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli)
@ -10,74 +9,10 @@ cli is a simple, fast, and fun package for building command line apps in Go. The
goal is to enable developers to write fast and distributable command line
applications in an expressive way.
## Usage Documentation
## Documentation
Usage documentation exists for each major version. Don't know what version you're on? You're probably using the version from the `main` branch, which is currently `v2`.
- `v2` - [./docs/v2/manual.md](./docs/v2/manual.md)
- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md)
Guides for migrating to newer versions:
- `v1-to-v2` - [./docs/migrate-v1-to-v2.md](./docs/migrate-v1-to-v2.md)
## Installation
Using this package requires a working Go environment. [See the install instructions for Go](http://golang.org/doc/install.html).
Go Modules are required when using this package. [See the go blog guide on using Go Modules](https://blog.golang.org/using-go-modules).
### Using `v2` releases
```
$ go get github.com/urfave/cli/v2
```
```go
...
import (
"github.com/urfave/cli/v2" // imports as package "cli"
)
...
```
### Using `v1` releases
```
$ go get github.com/urfave/cli
```
```go
...
import (
"github.com/urfave/cli"
)
...
```
### Build tags
You can use the following build tags:
#### `urfave_cli_no_docs`
When set, this removes `ToMarkdown` and `ToMan` methods, so your application
won't be able to call those. This reduces the resulting binary size by about
300-400 KB (measured using Go 1.18.1 on Linux/amd64), due to fewer dependencies.
### GOPATH
Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can
be easily used:
```
export PATH=$PATH:$GOPATH/bin
```
### Supported platforms
cli is tested against multiple versions of Go on Linux, and against the latest
released version of Go on OS X and Windows. This project uses Github Actions for
builds. To see our currently supported go versions and platforms, look at the [./.github/workflows/cli.yml](https://github.com/urfave/cli/blob/main/.github/workflows/cli.yml).
More documentation is available in [`./docs`](./docs) or the hosted
documentation site at <https://cli.urfave.org>.
## License

View file

@ -11,6 +11,8 @@ import (
"time"
)
const suggestDidYouMeanTemplate = "Did you mean %q?"
var (
changeLogURL = "https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md"
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
@ -18,6 +20,10 @@ var (
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
SuggestFlag SuggestFlagFunc = suggestFlag
SuggestCommand SuggestCommandFunc = suggestCommand
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
)
// App is the main structure of a cli application. It is recommended that
@ -52,6 +58,8 @@ type App struct {
HideVersion bool
// categories contains the categorized commands and is populated on app startup
categories CommandCategories
// flagCategories contains the categorized flags and is populated on app startup
flagCategories FlagCategories
// An action to execute when the shell completion flag is set
BashComplete BashCompleteFunc
// An action to execute before any subcommands are run, but after the context is ready
@ -100,6 +108,10 @@ type App struct {
didSetup bool
}
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
type SuggestCommandFunc func(commands []*Command, provided string) string
// Tries to find out when this binary was compiled.
// Returns the current time if it fails to find it.
func compileTime() time.Time {
@ -183,6 +195,8 @@ func (a *App) Setup() {
if c.HelpName == "" {
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
}
c.flagCategories = newFlagCategoriesFromFlags(c.Flags)
newCommands = append(newCommands, c)
}
a.Commands = newCommands
@ -207,6 +221,13 @@ func (a *App) Setup() {
}
sort.Sort(a.categories.(*commandCategories))
a.flagCategories = newFlagCategories()
for _, fl := range a.Flags {
if cf, ok := fl.(CategorizableFlag); ok {
a.flagCategories.AddFlag(cf.GetCategory(), cf)
}
}
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
@ -332,6 +353,29 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
return err
}
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
flag, parseErr := flagFromError(err)
if parseErr != nil {
return "", err
}
flags := a.Flags
if command != "" {
cmd := a.Command(command)
if cmd == nil {
return "", err
}
flags = cmd.Flags
}
suggestion := SuggestFlag(flags, flag, a.HideHelp)
if len(suggestion) == 0 {
return "", err
}
return fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", suggestion), nil
}
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
@ -493,6 +537,14 @@ func (a *App) VisibleCommands() []*Command {
return ret
}
// VisibleFlagCategories returns a slice containing all the categories with the flags they contain
func (a *App) VisibleFlagCategories() []VisibleFlagCategory {
if a.flagCategories == nil {
return []VisibleFlagCategory{}
}
return a.flagCategories.VisibleCategories()
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (a *App) VisibleFlags() []Flag {
return visibleFlags(a.Flags)

View file

@ -1,10 +1,12 @@
package cli
import "sort"
// CommandCategories interface allows for category manipulation
type CommandCategories interface {
// AddCommand adds a command to a category, creating a new category if necessary.
AddCommand(category string, command *Command)
// categories returns a copy of the category slice
// Categories returns a slice of categories sorted by name
Categories() []CommandCategory
}
@ -77,3 +79,93 @@ func (c *commandCategory) VisibleCommands() []*Command {
}
return ret
}
// FlagCategories interface allows for category manipulation
type FlagCategories interface {
// AddFlags adds a flag to a category, creating a new category if necessary.
AddFlag(category string, fl Flag)
// VisibleCategories returns a slice of visible flag categories sorted by name
VisibleCategories() []VisibleFlagCategory
}
type defaultFlagCategories struct {
m map[string]*defaultVisibleFlagCategory
}
func newFlagCategories() FlagCategories {
return &defaultFlagCategories{
m: map[string]*defaultVisibleFlagCategory{},
}
}
func newFlagCategoriesFromFlags(fs []Flag) FlagCategories {
fc := newFlagCategories()
for _, fl := range fs {
if cf, ok := fl.(CategorizableFlag); ok {
fc.AddFlag(cf.GetCategory(), cf)
}
}
return fc
}
func (f *defaultFlagCategories) AddFlag(category string, fl Flag) {
if _, ok := f.m[category]; !ok {
f.m[category] = &defaultVisibleFlagCategory{name: category, m: map[string]Flag{}}
}
f.m[category].m[fl.String()] = fl
}
func (f *defaultFlagCategories) VisibleCategories() []VisibleFlagCategory {
catNames := []string{}
for name := range f.m {
catNames = append(catNames, name)
}
sort.Strings(catNames)
ret := make([]VisibleFlagCategory, len(catNames))
for i, name := range catNames {
ret[i] = f.m[name]
}
return ret
}
// VisibleFlagCategory is a category containing flags.
type VisibleFlagCategory interface {
// Name returns the category name string
Name() string
// Flags returns a slice of VisibleFlag sorted by name
Flags() []VisibleFlag
}
type defaultVisibleFlagCategory struct {
name string
m map[string]Flag
}
func (fc *defaultVisibleFlagCategory) Name() string {
return fc.name
}
func (fc *defaultVisibleFlagCategory) Flags() []VisibleFlag {
vfNames := []string{}
for flName, fl := range fc.m {
if vf, ok := fl.(VisibleFlag); ok {
if vf.IsVisible() {
vfNames = append(vfNames, flName)
}
}
}
sort.Strings(vfNames)
ret := make([]VisibleFlag, len(vfNames))
for i, flName := range vfNames {
ret[i] = fc.m[flName].(VisibleFlag)
}
return ret
}

View file

@ -39,6 +39,7 @@ type Command struct {
Subcommands []*Command
// List of flags to parse
Flags []Flag
flagCategories FlagCategories
// Treat all flags as normal arguments if true
SkipFlagParsing bool
// Boolean to hide built-in help command and help flag
@ -286,6 +287,14 @@ func (c *Command) startApp(ctx *Context) error {
return app.RunAsSubcommand(ctx)
}
// VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory {
if c.flagCategories == nil {
return []VisibleFlagCategory{}
}
return c.flagCategories.VisibleCategories()
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (c *Command) VisibleFlags() []Flag {
return visibleFlags(c.Flags)

View file

@ -132,6 +132,14 @@ type VisibleFlag interface {
IsVisible() bool
}
// CategorizableFlag is an interface that allows us to potentially
// use a flag in a categorized representation.
type CategorizableFlag interface {
VisibleFlag
GetCategory() string
}
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
set := flag.NewFlagSet(name, flag.ContinueOnError)
@ -386,21 +394,24 @@ func hasFlag(flags []Flag, fl Flag) bool {
return false
}
func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) {
// Return the first value from a list of environment variables and files
// (which may or may not exist), a description of where the value was found,
// and a boolean which is true if a value was found.
func flagFromEnvOrFile(envVars []string, filePath string) (value string, fromWhere string, found bool) {
for _, envVar := range envVars {
envVar = strings.TrimSpace(envVar)
if val, ok := syscall.Getenv(envVar); ok {
return val, true
if value, found := syscall.Getenv(envVar); found {
return value, fmt.Sprintf("environment variable %q", envVar), true
}
}
for _, fileVar := range strings.Split(filePath, ",") {
if fileVar != "" {
if data, err := ioutil.ReadFile(fileVar); err == nil {
return string(data), true
return string(data), fmt.Sprintf("file %q", filePath), true
}
}
}
return "", false
return "", "", false
}
func flagSplitMultiValues(val string) []string {

View file

@ -16,6 +16,11 @@ func (f *BoolFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *BoolFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *BoolFlag) GetValue() string {
@ -37,12 +42,12 @@ func (f *BoolFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valBool, err := strconv.ParseBool(val)
if err != nil {
return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as bool value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = valBool

View file

@ -16,6 +16,11 @@ func (f *DurationFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *DurationFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *DurationFlag) GetValue() string {
@ -37,12 +42,12 @@ func (f *DurationFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valDuration, err := time.ParseDuration(val)
if err != nil {
return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as duration value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = valDuration

View file

@ -16,6 +16,11 @@ func (f *Float64Flag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *Float64Flag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *Float64Flag) GetValue() string {
@ -37,11 +42,11 @@ func (f *Float64Flag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *Float64Flag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valFloat, err := strconv.ParseFloat(val, 64)
if err != nil {
return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as float64 value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = valFloat

View file

@ -91,6 +91,11 @@ func (f *Float64SliceFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *Float64SliceFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *Float64SliceFlag) GetValue() string {
@ -115,13 +120,13 @@ func (f *Float64SliceFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
f.Value = &Float64Slice{}
for _, s := range flagSplitMultiValues(val) {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err)
return fmt.Errorf("could not parse %q as float64 slice value from %s for flag %s: %s", f.Value, source, f.Name, err)
}
}

View file

@ -21,6 +21,11 @@ func (f *GenericFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *GenericFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *GenericFlag) GetValue() string {
@ -46,10 +51,10 @@ func (f *GenericFlag) GetEnvVars() []string {
// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
func (f GenericFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
if err := f.Value.Set(val); err != nil {
return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q from %s as value for flag %s: %s", val, source, f.Name, err)
}
f.HasBeenSet = true

View file

@ -16,6 +16,11 @@ func (f *IntFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *IntFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *IntFlag) GetValue() string {
@ -37,12 +42,12 @@ func (f *IntFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseInt(val, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = int(valInt)

View file

@ -16,6 +16,11 @@ func (f *Int64Flag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *Int64Flag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *Int64Flag) GetValue() string {
@ -37,12 +42,12 @@ func (f *Int64Flag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseInt(val, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = valInt

View file

@ -88,10 +88,15 @@ func (f *Int64SliceFlag) TakesValue() bool {
}
// GetUsage returns the usage string for the flag
func (f Int64SliceFlag) GetUsage() string {
func (f *Int64SliceFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *Int64SliceFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *Int64SliceFlag) GetValue() string {
@ -116,12 +121,12 @@ func (f *Int64SliceFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = &Int64Slice{}
for _, s := range flagSplitMultiValues(val) {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as int64 slice value from %s for flag %s: %s", val, source, f.Name, err)
}
}

View file

@ -99,10 +99,15 @@ func (f *IntSliceFlag) TakesValue() bool {
}
// GetUsage returns the usage string for the flag
func (f IntSliceFlag) GetUsage() string {
func (f *IntSliceFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *IntSliceFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *IntSliceFlag) GetValue() string {
@ -127,12 +132,12 @@ func (f *IntSliceFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = &IntSlice{}
for _, s := range flagSplitMultiValues(val) {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as int slice value from %s for flag %s: %s", val, source, f.Name, err)
}
}

View file

@ -17,6 +17,11 @@ func (f *PathFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *PathFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *PathFlag) GetValue() string {
@ -41,7 +46,7 @@ func (f *PathFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *PathFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = val
f.HasBeenSet = true
}

View file

@ -15,6 +15,11 @@ func (f *StringFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *StringFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *StringFlag) GetValue() string {
@ -39,7 +44,7 @@ func (f *StringFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *StringFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = val
f.HasBeenSet = true
}

View file

@ -86,6 +86,11 @@ func (f *StringSliceFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *StringSliceFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *StringSliceFlag) GetValue() string {
@ -117,7 +122,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
}
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if f.Value == nil {
f.Value = &StringSlice{}
}
@ -128,7 +133,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
for _, s := range flagSplitMultiValues(val) {
if err := destination.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as string value from %s for flag %s: %s", val, source, f.Name, err)
}
}

View file

@ -68,6 +68,11 @@ func (f *TimestampFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *TimestampFlag) GetCategory() string {
return f.Category
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *TimestampFlag) GetValue() string {
@ -104,9 +109,9 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
f.Destination.SetLayout(f.Layout)
}
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if err := f.Value.Set(val); err != nil {
return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as timestamp value from %s for flag %s: %s", val, source, f.Name, err)
}
f.HasBeenSet = true
}

View file

@ -16,13 +16,18 @@ func (f *UintFlag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *UintFlag) GetCategory() string {
return f.Category
}
// Apply populates the flag given the flag set and environment
func (f *UintFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseUint(val, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as uint value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = uint(valInt)

View file

@ -16,13 +16,18 @@ func (f *Uint64Flag) GetUsage() string {
return f.Usage
}
// GetCategory returns the category for the flag
func (f *Uint64Flag) GetCategory() string {
return f.Category
}
// Apply populates the flag given the flag set and environment
func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseUint(val, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, f.Name, err)
return fmt.Errorf("could not parse %q as uint64 value from %s for flag %s: %s", val, source, f.Name, err)
}
f.Value = valInt

View file

@ -26,6 +26,11 @@ application:
VARIABLES
var (
SuggestFlag SuggestFlagFunc = suggestFlag
SuggestCommand SuggestCommandFunc = suggestCommand
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
)
var AppHelpTemplate = `NAME:
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
@ -45,11 +50,16 @@ AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}}
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}
{{if .Name}}{{.Name}}
{{end}}{{range .Flags}}{{.}}
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
{{end}}{{$option}}{{end}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
@ -68,11 +78,16 @@ CATEGORY:
{{.Category}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleFlags}}
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleFlagCategories}}
OPTIONS:{{range .VisibleFlagCategories}}
{{if .Name}}{{.Name}}
{{end}}{{range .Flags}}{{.}}
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
{{end}}{{end}}{{end}}
`
CommandHelpTemplate is the text template for the command help topic. cli.go
uses text/template to render templates. You can render custom help text by
@ -369,6 +384,10 @@ func (a *App) VisibleCategories() []CommandCategory
func (a *App) VisibleCommands() []*Command
VisibleCommands returns a slice of the Commands with Hidden=false
func (a *App) VisibleFlagCategories() []VisibleFlagCategory
VisibleFlagCategories returns a slice containing all the categories with the
flags they contain
func (a *App) VisibleFlags() []Flag
VisibleFlags returns a slice of the Flags with Hidden=false
@ -409,6 +428,7 @@ type BeforeFunc func(*Context) error
type BoolFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -431,6 +451,9 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) error
func (f *BoolFlag) Get(ctx *Context) bool
Get returns the flags value in the given Context.
func (f *BoolFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *BoolFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -462,6 +485,14 @@ func (f *BoolFlag) String() string
func (f *BoolFlag) TakesValue() bool
TakesValue returns true of the flag takes a value, otherwise false
type CategorizableFlag interface {
VisibleFlag
GetCategory() string
}
CategorizableFlag is an interface that allows us to potentially use a flag
in a categorized representation.
type Command struct {
// The name of the command
Name string
@ -493,6 +524,7 @@ type Command struct {
Subcommands []*Command
// List of flags to parse
Flags []Flag
// Treat all flags as normal arguments if true
SkipFlagParsing bool
// Boolean to hide built-in help command and help flag
@ -532,13 +564,17 @@ func (c *Command) Run(ctx *Context) (err error)
Run invokes the command given the context, parses ctx.Args() to generate
command-specific flags
func (c *Command) VisibleFlagCategories() []VisibleFlagCategory
VisibleFlagCategories returns a slice containing all the visible flag
categories with the flags they contain
func (c *Command) VisibleFlags() []Flag
VisibleFlags returns a slice of the Flags with Hidden=false
type CommandCategories interface {
// AddCommand adds a command to a category, creating a new category if necessary.
AddCommand(category string, command *Command)
// categories returns a copy of the category slice
// Categories returns a slice of categories sorted by name
Categories() []CommandCategory
}
CommandCategories interface allows for category manipulation
@ -682,6 +718,7 @@ type DocGenerationFlag interface {
type DurationFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -704,6 +741,9 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) error
func (f *DurationFlag) Get(ctx *Context) time.Duration
Get returns the flags value in the given Context.
func (f *DurationFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *DurationFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -799,6 +839,14 @@ var VersionFlag Flag = &BoolFlag{
}
VersionFlag prints the version for the application
type FlagCategories interface {
// AddFlags adds a flag to a category, creating a new category if necessary.
AddFlag(category string, fl Flag)
// VisibleCategories returns a slice of visible flag categories sorted by name
VisibleCategories() []VisibleFlagCategory
}
FlagCategories interface allows for category manipulation
type FlagEnvHintFunc func(envVars []string, str string) string
FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help
with the environment variable details.
@ -843,6 +891,7 @@ func (f FlagsByName) Swap(i, j int)
type Float64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -865,6 +914,9 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) error
func (f *Float64Flag) Get(ctx *Context) float64
Get returns the flags value in the given Context.
func (f *Float64Flag) GetCategory() string
GetCategory returns the category for the flag
func (f *Float64Flag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -922,6 +974,7 @@ func (f *Float64Slice) Value() []float64
type Float64SliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -944,6 +997,9 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error
func (f *Float64SliceFlag) Get(ctx *Context) []float64
Get returns the flags value in the given Context.
func (f *Float64SliceFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *Float64SliceFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -984,6 +1040,7 @@ type Generic interface {
type GenericFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1009,6 +1066,9 @@ func (f GenericFlag) Apply(set *flag.FlagSet) error
func (f *GenericFlag) Get(ctx *Context) interface{}
Get returns the flags value in the given Context.
func (f *GenericFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *GenericFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1043,6 +1103,7 @@ func (f *GenericFlag) TakesValue() bool
type Int64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1065,6 +1126,9 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error
func (f *Int64Flag) Get(ctx *Context) int64
Get returns the flags value in the given Context.
func (f *Int64Flag) GetCategory() string
GetCategory returns the category for the flag
func (f *Int64Flag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1122,6 +1186,7 @@ func (i *Int64Slice) Value() []int64
type Int64SliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1144,13 +1209,16 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error
func (f *Int64SliceFlag) Get(ctx *Context) []int64
Get returns the flags value in the given Context.
func (f *Int64SliceFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *Int64SliceFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
func (f *Int64SliceFlag) GetEnvVars() []string
GetEnvVars returns the env vars for this flag
func (f Int64SliceFlag) GetUsage() string
func (f *Int64SliceFlag) GetUsage() string
GetUsage returns the usage string for the flag
func (f *Int64SliceFlag) GetValue() string
@ -1178,6 +1246,7 @@ func (f *Int64SliceFlag) TakesValue() bool
type IntFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1200,6 +1269,9 @@ func (f *IntFlag) Apply(set *flag.FlagSet) error
func (f *IntFlag) Get(ctx *Context) int
Get returns the flags value in the given Context.
func (f *IntFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *IntFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1261,6 +1333,7 @@ func (i *IntSlice) Value() []int
type IntSliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1283,13 +1356,16 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error
func (f *IntSliceFlag) Get(ctx *Context) []int
Get returns the flags value in the given Context.
func (f *IntSliceFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *IntSliceFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
func (f *IntSliceFlag) GetEnvVars() []string
GetEnvVars returns the env vars for this flag
func (f IntSliceFlag) GetUsage() string
func (f *IntSliceFlag) GetUsage() string
GetUsage returns the usage string for the flag
func (f *IntSliceFlag) GetValue() string
@ -1331,6 +1407,7 @@ type Path = string
type PathFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1355,6 +1432,9 @@ func (f *PathFlag) Apply(set *flag.FlagSet) error
func (f *PathFlag) Get(ctx *Context) string
Get returns the flags value in the given Context.
func (f *PathFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *PathFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1403,6 +1483,7 @@ type Serializer interface {
type StringFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1427,6 +1508,9 @@ func (f *StringFlag) Apply(set *flag.FlagSet) error
func (f *StringFlag) Get(ctx *Context) string
Get returns the flags value in the given Context.
func (f *StringFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *StringFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1484,6 +1568,7 @@ func (s *StringSlice) Value() []string
type StringSliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1508,6 +1593,9 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error
func (f *StringSliceFlag) Get(ctx *Context) []string
Get returns the flags value in the given Context.
func (f *StringSliceFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *StringSliceFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1539,6 +1627,10 @@ func (f *StringSliceFlag) String() string
func (f *StringSliceFlag) TakesValue() bool
TakesValue returns true of the flag takes a value, otherwise false
type SuggestCommandFunc func(commands []*Command, provided string) string
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
type Timestamp struct {
// Has unexported fields.
}
@ -1568,6 +1660,7 @@ func (t *Timestamp) Value() *time.Time
type TimestampFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1592,6 +1685,9 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error
func (f *TimestampFlag) Get(ctx *Context) *time.Time
Get returns the flags value in the given Context.
func (f *TimestampFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *TimestampFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1626,6 +1722,7 @@ func (f *TimestampFlag) TakesValue() bool
type Uint64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1648,6 +1745,9 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error
func (f *Uint64Flag) Get(ctx *Context) uint64
Get returns the flags value in the given Context.
func (f *Uint64Flag) GetCategory() string
GetCategory returns the category for the flag
func (f *Uint64Flag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1682,6 +1782,7 @@ func (f *Uint64Flag) TakesValue() bool
type UintFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -1704,6 +1805,9 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error
func (f *UintFlag) Get(ctx *Context) uint
Get returns the flags value in the given Context.
func (f *UintFlag) GetCategory() string
GetCategory returns the category for the flag
func (f *UintFlag) GetDefaultText() string
GetDefaultText returns the default text for this flag
@ -1743,6 +1847,14 @@ type VisibleFlag interface {
}
VisibleFlag is an interface that allows to check if a flag is visible
type VisibleFlagCategory interface {
// Name returns the category name string
Name() string
// Flags returns a slice of VisibleFlag sorted by name
Flags() []VisibleFlag
}
VisibleFlagCategory is a category containing flags.
package altsrc // import "github.com/urfave/cli/v2/altsrc"

View file

@ -107,7 +107,7 @@ func printCommandSuggestions(commands []*Command, writer io.Writer) {
if command.Hidden {
continue
}
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
if strings.HasSuffix(os.Getenv("SHELL"), "zsh") {
for _, name := range command.Names() {
_, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage)
}
@ -221,7 +221,7 @@ func ShowCommandHelp(ctx *Context, command string) error {
if ctx.App.CommandNotFound == nil {
errMsg := fmt.Sprintf("No help topic for '%v'", command)
if ctx.App.Suggest {
if suggestion := suggestCommand(ctx.App.Commands, command); suggestion != "" {
if suggestion := SuggestCommand(ctx.App.Commands, command); suggestion != "" {
errMsg += ". " + suggestion
}
}

View file

@ -3,44 +3,29 @@ package cli
import (
"fmt"
"github.com/antzucaro/matchr"
"github.com/xrash/smetrics"
)
const didYouMeanTemplate = "Did you mean '%s'?"
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
flag, parseErr := flagFromError(err)
if parseErr != nil {
return "", err
func jaroWinkler(a, b string) float64 {
// magic values are from https://github.com/xrash/smetrics/blob/039620a656736e6ad994090895784a7af15e0b80/jaro-winkler.go#L8
const (
boostThreshold = 0.7
prefixSize = 4
)
return smetrics.JaroWinkler(a, b, boostThreshold, prefixSize)
}
flags := a.Flags
if command != "" {
cmd := a.Command(command)
if cmd == nil {
return "", err
}
flags = cmd.Flags
}
suggestion := a.suggestFlag(flags, flag)
if len(suggestion) == 0 {
return "", err
}
return fmt.Sprintf(didYouMeanTemplate+"\n\n", suggestion), nil
}
func (a *App) suggestFlag(flags []Flag, provided string) (suggestion string) {
func suggestFlag(flags []Flag, provided string, hideHelp bool) string {
distance := 0.0
suggestion := ""
for _, flag := range flags {
flagNames := flag.Names()
if !a.HideHelp {
if !hideHelp {
flagNames = append(flagNames, HelpFlag.Names()...)
}
for _, name := range flagNames {
newDistance := matchr.JaroWinkler(name, provided, true)
newDistance := jaroWinkler(name, provided)
if newDistance > distance {
distance = newDistance
suggestion = name
@ -63,7 +48,7 @@ func suggestCommand(commands []*Command, provided string) (suggestion string) {
distance := 0.0
for _, command := range commands {
for _, name := range append(command.Names(), helpName, helpAlias) {
newDistance := matchr.JaroWinkler(name, provided, true)
newDistance := jaroWinkler(name, provided)
if newDistance > distance {
distance = newDistance
suggestion = name
@ -71,5 +56,5 @@ func suggestCommand(commands []*Command, provided string) (suggestion string) {
}
}
return fmt.Sprintf(didYouMeanTemplate, suggestion)
return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion)
}

View file

@ -22,11 +22,16 @@ AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}}
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}
{{if .Name}}{{.Name}}
{{end}}{{range .Flags}}{{.}}
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
{{end}}{{$option}}{{end}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
@ -45,11 +50,16 @@ CATEGORY:
{{.Category}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleFlags}}
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleFlagCategories}}
OPTIONS:{{range .VisibleFlagCategories}}
{{if .Name}}{{.Name}}
{{end}}{{range .Flags}}{{.}}
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
{{end}}{{end}}{{end}}
`
// SubcommandHelpTemplate is the text template for the subcommand help topic.

View file

@ -8,6 +8,7 @@ import "time"
type Float64SliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -47,6 +48,7 @@ func (f *Float64SliceFlag) IsVisible() bool {
type GenericFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -93,6 +95,7 @@ func (f *GenericFlag) IsVisible() bool {
type Int64SliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -132,6 +135,7 @@ func (f *Int64SliceFlag) IsVisible() bool {
type IntSliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -171,6 +175,7 @@ func (f *IntSliceFlag) IsVisible() bool {
type PathFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -217,6 +222,7 @@ func (f *PathFlag) IsVisible() bool {
type StringSliceFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -258,6 +264,7 @@ func (f *StringSliceFlag) IsVisible() bool {
type TimestampFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -304,6 +311,7 @@ func (f *TimestampFlag) IsVisible() bool {
type BoolFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -348,6 +356,7 @@ func (f *BoolFlag) IsVisible() bool {
type Float64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -392,6 +401,7 @@ func (f *Float64Flag) IsVisible() bool {
type IntFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -436,6 +446,7 @@ func (f *IntFlag) IsVisible() bool {
type Int64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -480,6 +491,7 @@ func (f *Int64Flag) IsVisible() bool {
type StringFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -526,6 +538,7 @@ func (f *StringFlag) IsVisible() bool {
type DurationFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -570,6 +583,7 @@ func (f *DurationFlag) IsVisible() bool {
type UintFlag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string
@ -614,6 +628,7 @@ func (f *UintFlag) IsVisible() bool {
type Uint64Flag struct {
Name string
Category string
DefaultText string
FilePath string
Usage string

9
vendor/github.com/xrash/smetrics/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,9 @@
language: go
go:
- 1.11
- 1.12
- 1.13
- 1.14.x
- master
script:
- cd tests && make

21
vendor/github.com/xrash/smetrics/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
Copyright (C) 2016 Felipe da Cunha Gonçalves
All Rights Reserved.
MIT LICENSE
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.

49
vendor/github.com/xrash/smetrics/README.md generated vendored Normal file
View file

@ -0,0 +1,49 @@
[![Build Status](https://travis-ci.org/xrash/smetrics.svg?branch=master)](http://travis-ci.org/xrash/smetrics)
# smetrics
`smetrics` is "string metrics".
Package smetrics provides a bunch of algorithms for calculating the distance between strings.
There are implementations for calculating the popular Levenshtein distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro distance, the Jaro-Winkler distance, and more.
# How to import
```go
import "github.com/xrash/smetrics"
```
# Documentation
Go to [https://pkg.go.dev/github.com/xrash/smetrics](https://pkg.go.dev/github.com/xrash/smetrics) for complete documentation.
# Example
```go
package main
import (
"github.com/xrash/smetrics"
)
func main() {
smetrics.WagnerFischer("POTATO", "POTATTO", 1, 1, 2)
smetrics.WagnerFischer("MOUSE", "HOUSE", 2, 2, 4)
smetrics.Ukkonen("POTATO", "POTATTO", 1, 1, 2)
smetrics.Ukkonen("MOUSE", "HOUSE", 2, 2, 4)
smetrics.Jaro("AL", "AL")
smetrics.Jaro("MARTHA", "MARHTA")
smetrics.JaroWinkler("AL", "AL", 0.7, 4)
smetrics.JaroWinkler("MARTHA", "MARHTA", 0.7, 4)
smetrics.Soundex("Euler")
smetrics.Soundex("Ellery")
smetrics.Hamming("aaa", "aaa")
smetrics.Hamming("aaa", "aab")
}
```

19
vendor/github.com/xrash/smetrics/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Package smetrics provides a bunch of algorithms for calculating
the distance between strings.
There are implementations for calculating the popular Levenshtein
distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro
distance, the Jaro-Winkler distance, and more.
For the Levenshtein distance, you can use the functions WagnerFischer()
and Ukkonen(). Read the documentation on these functions.
For the Jaro and Jaro-Winkler algorithms, check the functions
Jaro() and JaroWinkler(). Read the documentation on these functions.
For the Soundex algorithm, check the function Soundex().
For the Hamming distance algorithm, check the function Hamming().
*/
package smetrics

25
vendor/github.com/xrash/smetrics/hamming.go generated vendored Normal file
View file

@ -0,0 +1,25 @@
package smetrics
import (
"fmt"
)
// The Hamming distance is the minimum number of substitutions required to change string A into string B. Both strings must have the same size. If the strings have different sizes, the function returns an error.
func Hamming(a, b string) (int, error) {
al := len(a)
bl := len(b)
if al != bl {
return -1, fmt.Errorf("strings are not equal (len(a)=%d, len(b)=%d)", al, bl)
}
var difference = 0
for i := range a {
if a[i] != b[i] {
difference = difference + 1
}
}
return difference, nil
}

28
vendor/github.com/xrash/smetrics/jaro-winkler.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
package smetrics
import (
"math"
)
// The Jaro-Winkler distance. The result is 1 for equal strings, and 0 for completely different strings. It is commonly used on Record Linkage stuff, thus it tries to be accurate for common typos when writing real names such as person names and street names.
// Jaro-Winkler is a modification of the Jaro algorithm. It works by first running Jaro, then boosting the score of exact matches at the beginning of the strings. Because of that, it introduces two more parameters: the boostThreshold and the prefixSize. These are commonly set to 0.7 and 4, respectively.
func JaroWinkler(a, b string, boostThreshold float64, prefixSize int) float64 {
j := Jaro(a, b)
if j <= boostThreshold {
return j
}
prefixSize = int(math.Min(float64(len(a)), math.Min(float64(prefixSize), float64(len(b)))))
var prefixMatch float64
for i := 0; i < prefixSize; i++ {
if a[i] == b[i] {
prefixMatch++
} else {
break
}
}
return j + 0.1*prefixMatch*(1.0-j)
}

86
vendor/github.com/xrash/smetrics/jaro.go generated vendored Normal file
View file

@ -0,0 +1,86 @@
package smetrics
import (
"math"
)
// The Jaro distance. The result is 1 for equal strings, and 0 for completely different strings.
func Jaro(a, b string) float64 {
// If both strings are zero-length, they are completely equal,
// therefore return 1.
if len(a) == 0 && len(b) == 0 {
return 1
}
// If one string is zero-length, strings are completely different,
// therefore return 0.
if len(a) == 0 || len(b) == 0 {
return 0
}
// Define the necessary variables for the algorithm.
la := float64(len(a))
lb := float64(len(b))
matchRange := int(math.Max(0, math.Floor(math.Max(la, lb)/2.0)-1))
matchesA := make([]bool, len(a))
matchesB := make([]bool, len(b))
var matches float64 = 0
// Step 1: Matches
// Loop through each character of the first string,
// looking for a matching character in the second string.
for i := 0; i < len(a); i++ {
start := int(math.Max(0, float64(i-matchRange)))
end := int(math.Min(lb-1, float64(i+matchRange)))
for j := start; j <= end; j++ {
if matchesB[j] {
continue
}
if a[i] == b[j] {
matchesA[i] = true
matchesB[j] = true
matches++
break
}
}
}
// If there are no matches, strings are completely different,
// therefore return 0.
if matches == 0 {
return 0
}
// Step 2: Transpositions
// Loop through the matches' arrays, looking for
// unaligned matches. Count the number of unaligned matches.
unaligned := 0
j := 0
for i := 0; i < len(a); i++ {
if !matchesA[i] {
continue
}
for !matchesB[j] {
j++
}
if a[i] != b[j] {
unaligned++
}
j++
}
// The number of unaligned matches divided by two, is the number of _transpositions_.
transpositions := math.Floor(float64(unaligned / 2))
// Jaro distance is the average between these three numbers:
// 1. matches / length of string A
// 2. matches / length of string B
// 3. (matches - transpositions/matches)
// So, all that divided by three is the final result.
return ((matches / la) + (matches / lb) + ((matches - transpositions) / matches)) / 3.0
}

41
vendor/github.com/xrash/smetrics/soundex.go generated vendored Normal file
View file

@ -0,0 +1,41 @@
package smetrics
import (
"strings"
)
// The Soundex encoding. It is a phonetic algorithm that considers how the words sound in English. Soundex maps a string to a 4-byte code consisting of the first letter of the original string and three numbers. Strings that sound similar should map to the same code.
func Soundex(s string) string {
m := map[byte]string{
'B': "1", 'P': "1", 'F': "1", 'V': "1",
'C': "2", 'S': "2", 'K': "2", 'G': "2", 'J': "2", 'Q': "2", 'X': "2", 'Z': "2",
'D': "3", 'T': "3",
'L': "4",
'M': "5", 'N': "5",
'R': "6",
}
s = strings.ToUpper(s)
r := string(s[0])
p := s[0]
for i := 1; i < len(s) && len(r) < 4; i++ {
c := s[i]
if (c < 'A' || c > 'Z') || (c == p) {
continue
}
p = c
if n, ok := m[c]; ok {
r += n
}
}
for i := len(r); i < 4; i++ {
r += "0"
}
return r
}

94
vendor/github.com/xrash/smetrics/ukkonen.go generated vendored Normal file
View file

@ -0,0 +1,94 @@
package smetrics
import (
"math"
)
// The Ukkonen algorithm for calculating the Levenshtein distance. The algorithm is described in http://www.cs.helsinki.fi/u/ukkonen/InfCont85.PDF, or in docs/InfCont85.PDF. It runs on O(t . min(m, n)) where t is the actual distance between strings a and b. It needs O(min(t, m, n)) space. This function might be preferred over WagnerFischer() for *very* similar strings. But test it out yourself.
// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively.
func Ukkonen(a, b string, icost, dcost, scost int) int {
var lowerCost int
if icost < dcost && icost < scost {
lowerCost = icost
} else if dcost < scost {
lowerCost = dcost
} else {
lowerCost = scost
}
infinite := math.MaxInt32 / 2
var r []int
var k, kprime, p, t int
var ins, del, sub int
if len(a) > len(b) {
t = (len(a) - len(b) + 1) * lowerCost
} else {
t = (len(b) - len(a) + 1) * lowerCost
}
for {
if (t / lowerCost) < (len(b) - len(a)) {
continue
}
// This is the right damn thing since the original Ukkonen
// paper minimizes the expression result only, but the uncommented version
// doesn't need to deal with floats so it's faster.
// p = int(math.Floor(0.5*((float64(t)/float64(lowerCost)) - float64(len(b) - len(a)))))
p = ((t / lowerCost) - (len(b) - len(a))) / 2
k = -p
kprime = k
rowlength := (len(b) - len(a)) + (2 * p)
r = make([]int, rowlength+2)
for i := 0; i < rowlength+2; i++ {
r[i] = infinite
}
for i := 0; i <= len(a); i++ {
for j := 0; j <= rowlength; j++ {
if i == j+k && i == 0 {
r[j] = 0
} else {
if j-1 < 0 {
ins = infinite
} else {
ins = r[j-1] + icost
}
del = r[j+1] + dcost
sub = r[j] + scost
if i-1 < 0 || i-1 >= len(a) || j+k-1 >= len(b) || j+k-1 < 0 {
sub = infinite
} else if a[i-1] == b[j+k-1] {
sub = r[j]
}
if ins < del && ins < sub {
r[j] = ins
} else if del < sub {
r[j] = del
} else {
r[j] = sub
}
}
}
k++
}
if r[(len(b)-len(a))+(2*p)+kprime] <= t {
break
} else {
t *= 2
}
}
return r[(len(b)-len(a))+(2*p)+kprime]
}

48
vendor/github.com/xrash/smetrics/wagner-fischer.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
package smetrics
// The Wagner-Fischer algorithm for calculating the Levenshtein distance.
// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively.
func WagnerFischer(a, b string, icost, dcost, scost int) int {
// Allocate both rows.
row1 := make([]int, len(b)+1)
row2 := make([]int, len(b)+1)
var tmp []int
// Initialize the first row.
for i := 1; i <= len(b); i++ {
row1[i] = i * icost
}
// For each row...
for i := 1; i <= len(a); i++ {
row2[0] = i * dcost
// For each column...
for j := 1; j <= len(b); j++ {
if a[i-1] == b[j-1] {
row2[j] = row1[j-1]
} else {
ins := row2[j-1] + icost
del := row1[j] + dcost
sub := row1[j-1] + scost
if ins < del && ins < sub {
row2[j] = ins
} else if del < sub {
row2[j] = del
} else {
row2[j] = sub
}
}
}
// Swap the rows at the end of each row.
tmp = row1
row1 = row2
row2 = tmp
}
// Because we swapped the rows, the final result is in row1 instead of row2.
return row1[len(row1)-1]
}

View file

@ -315,6 +315,20 @@ type ServeConnOpts struct {
// requests. If nil, BaseConfig.Handler is used. If BaseConfig
// or BaseConfig.Handler is nil, http.DefaultServeMux is used.
Handler http.Handler
// UpgradeRequest is an initial request received on a connection
// undergoing an h2c upgrade. The request body must have been
// completely read from the connection before calling ServeConn,
// and the 101 Switching Protocols response written.
UpgradeRequest *http.Request
// Settings is the decoded contents of the HTTP2-Settings header
// in an h2c upgrade request.
Settings []byte
// SawClientPreface is set if the HTTP/2 connection preface
// has already been read from the connection.
SawClientPreface bool
}
func (o *ServeConnOpts) context() context.Context {
@ -383,6 +397,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
headerTableSize: initialHeaderTableSize,
serveG: newGoroutineLock(),
pushEnabled: true,
sawClientPreface: opts.SawClientPreface,
}
s.state.registerConn(sc)
@ -465,9 +480,27 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
}
}
if opts.Settings != nil {
fr := &SettingsFrame{
FrameHeader: FrameHeader{valid: true},
p: opts.Settings,
}
if err := fr.ForeachSetting(sc.processSetting); err != nil {
sc.rejectConn(ErrCodeProtocol, "invalid settings")
return
}
opts.Settings = nil
}
if hook := testHookGetServerConn; hook != nil {
hook(sc)
}
if opts.UpgradeRequest != nil {
sc.upgradeRequest(opts.UpgradeRequest)
opts.UpgradeRequest = nil
}
sc.serve()
}
@ -512,6 +545,7 @@ type serverConn struct {
// Everything following is owned by the serve loop; use serveG.check():
serveG goroutineLock // used to verify funcs are on serve()
pushEnabled bool
sawClientPreface bool // preface has already been read, used in h2c upgrade
sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs?
@ -974,6 +1008,9 @@ var errPrefaceTimeout = errors.New("timeout waiting for client preface")
// returns errPrefaceTimeout on timeout, or an error if the greeting
// is invalid.
func (sc *serverConn) readPreface() error {
if sc.sawClientPreface {
return nil
}
errc := make(chan error, 1)
go func() {
// Read the client preface
@ -1915,6 +1952,26 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
return nil
}
func (sc *serverConn) upgradeRequest(req *http.Request) {
sc.serveG.check()
id := uint32(1)
sc.maxClientStreamID = id
st := sc.newStream(id, 0, stateHalfClosedRemote)
st.reqTrailer = req.Trailer
if st.reqTrailer != nil {
st.trailer = make(http.Header)
}
rw := sc.newResponseWriter(st, req)
// Disable any read deadline set by the net/http package
// prior to the upgrade.
if sc.hs.ReadTimeout != 0 {
sc.conn.SetReadDeadline(time.Time{})
}
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
}
func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
sc := st.sc
sc.serveG.check()
@ -2145,6 +2202,11 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
}
req = req.WithContext(st.ctx)
rw := sc.newResponseWriter(st, req)
return rw, req, nil
}
func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *responseWriter {
rws := responseWriterStatePool.Get().(*responseWriterState)
bwSave := rws.bw
*rws = responseWriterState{} // zero all the fields
@ -2153,10 +2215,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
rws.bw.Reset(chunkWriter{rws})
rws.stream = st
rws.req = req
rws.body = body
rw := &responseWriter{rws: rws}
return rw, req, nil
return &responseWriter{rws: rws}
}
// Run on its own goroutine.
@ -2371,7 +2430,6 @@ type responseWriterState struct {
// immutable within a request:
stream *stream
req *http.Request
body *requestBody // to close at end of request, if DATA frames didn't
conn *serverConn
// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc

View file

@ -139,6 +139,7 @@ func (f *credentialsFile) jwtConfig(scopes []string, subject string) *jwt.Config
Scopes: scopes,
TokenURL: f.TokenURL,
Subject: subject, // This is the user email to impersonate
Audience: f.Audience,
}
if cfg.TokenURL == "" {
cfg.TokenURL = JWTTokenURL

View file

@ -94,10 +94,10 @@ type Statfs_t struct {
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
F_fstypename [16]byte
F_mntonname [90]byte
F_mntfromname [90]byte
F_mntfromspec [90]byte
Pad_cgo_0 [2]byte
Mount_info [160]byte
}

View file

@ -96,10 +96,10 @@ type Statfs_t struct {
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
F_fstypename [16]byte
F_mntonname [90]byte
F_mntfromname [90]byte
F_mntfromspec [90]byte
_ [2]byte
Mount_info [160]byte
}

View file

@ -98,10 +98,10 @@ type Statfs_t struct {
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
F_fstypename [16]byte
F_mntonname [90]byte
F_mntfromname [90]byte
F_mntfromspec [90]byte
_ [2]byte
Mount_info [160]byte
}

View file

@ -94,10 +94,10 @@ type Statfs_t struct {
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
F_fstypename [16]byte
F_mntonname [90]byte
F_mntfromname [90]byte
F_mntfromspec [90]byte
_ [2]byte
Mount_info [160]byte
}

View file

@ -94,10 +94,10 @@ type Statfs_t struct {
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
F_fstypename [16]byte
F_mntonname [90]byte
F_mntfromname [90]byte
F_mntfromspec [90]byte
_ [2]byte
Mount_info [160]byte
}

View file

@ -5,4 +5,4 @@
package internal
// Version is the current tagged release of the library.
const Version = "0.80.0"
const Version = "0.81.0"

22
vendor/modules.txt vendored
View file

@ -1,4 +1,4 @@
# cloud.google.com/go v0.101.1
# cloud.google.com/go v0.102.0
## explicit; go 1.15
cloud.google.com/go
cloud.google.com/go/internal
@ -34,10 +34,7 @@ github.com/VictoriaMetrics/metricsql/binaryop
# github.com/VividCortex/ewma v1.2.0
## explicit; go 1.12
github.com/VividCortex/ewma
# github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0
## explicit; go 1.13
github.com/antzucaro/matchr
# github.com/aws/aws-sdk-go v1.44.18
# github.com/aws/aws-sdk-go v1.44.22
## explicit; go 1.11
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/arn
@ -228,7 +225,7 @@ github.com/rivo/uniseg
# github.com/russross/blackfriday/v2 v2.1.0
## explicit
github.com/russross/blackfriday/v2
# github.com/urfave/cli/v2 v2.7.1
# github.com/urfave/cli/v2 v2.8.1
## explicit; go 1.18
github.com/urfave/cli/v2
# github.com/valyala/bytebufferpool v1.0.0
@ -253,6 +250,9 @@ github.com/valyala/histogram
# github.com/valyala/quicktemplate v1.7.0
## explicit; go 1.11
github.com/valyala/quicktemplate
# github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673
## explicit
github.com/xrash/smetrics
# go.opencensus.io v0.23.0
## explicit; go 1.13
go.opencensus.io
@ -277,7 +277,7 @@ go.opencensus.io/trace/tracestate
go.uber.org/atomic
# go.uber.org/goleak v1.1.11-0.20210813005559-691160354723
## explicit; go 1.13
# golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
# golang.org/x/net v0.0.0-20220524220425-1d687d428aca
## explicit; go 1.17
golang.org/x/net/context
golang.org/x/net/context/ctxhttp
@ -289,7 +289,7 @@ golang.org/x/net/internal/socks
golang.org/x/net/internal/timeseries
golang.org/x/net/proxy
golang.org/x/net/trace
# golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
# golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401
## explicit; go 1.11
golang.org/x/oauth2
golang.org/x/oauth2/authhandler
@ -302,7 +302,7 @@ golang.org/x/oauth2/jwt
# golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
## explicit
golang.org/x/sync/errgroup
# golang.org/x/sys v0.0.0-20220519141025-dcacdad47464
# golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
## explicit; go 1.17
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix
@ -317,7 +317,7 @@ golang.org/x/text/unicode/norm
## explicit; go 1.17
golang.org/x/xerrors
golang.org/x/xerrors/internal
# google.golang.org/api v0.80.0
# google.golang.org/api v0.81.0
## explicit; go 1.15
google.golang.org/api/googleapi
google.golang.org/api/googleapi/transport
@ -350,7 +350,7 @@ google.golang.org/appengine/internal/socket
google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/socket
google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd
# google.golang.org/genproto v0.0.0-20220525015930-6ca3db687a9d
## explicit; go 1.15
google.golang.org/genproto/googleapis/api/annotations
google.golang.org/genproto/googleapis/iam/v1