Remove openfaas-cloud commands
OpenFaaS Cloud has long been deprecated, these commands should no longer be used by anyone. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
41
README.md
41
README.md
@@ -350,47 +350,6 @@ $ uname -a | curl http://127.0.0.1:8080/function/nodejs-echo--data-binary @-
|
||||
|
||||
> For further instructions on the manual CLI flags (without using a YAML file) read [manual_cli.md](https://github.com/openfaas/faas-cli/blob/master/MANUAL_CLI.md)
|
||||
|
||||
### OpenFaaS Cloud (extensions)
|
||||
|
||||
[OpenFaaS Cloud](https://github.com/openfaas/openfaas-cloud) provides a GitOps experience for functions on Kubernetes.
|
||||
|
||||
Commands:
|
||||
|
||||
* `seal`
|
||||
|
||||
You can use the CLI to seal a secret for usage on public Git repo. The pre-requisite is that you have installed [SealedSecrets](https://github.com/bitnami-labs/sealed-secrets) and exported your public key from your cluster as `pub-cert.pem`.
|
||||
|
||||
Install `kubeseal` using `faas-cli` or the [SealedSecrets docs](https://github.com/bitnami-labs/sealed-secrets):
|
||||
|
||||
```sh
|
||||
$ faas-cli cloud seal --download
|
||||
```
|
||||
|
||||
You can also download a specific version:
|
||||
|
||||
```sh
|
||||
$ faas-cli cloud seal --download --download-version v0.8.0
|
||||
```
|
||||
|
||||
Now grab your pub-cert.pem file from your cluster, or use the official [OpenFaaS Cloud certificate](https://github.com/openfaas/cloud-functions/blob/master/pub-cert.pem).
|
||||
|
||||
```sh
|
||||
$ kubeseal --fetch-cert --controller-name ofc-sealedsecrets-sealed-secrets > pub-cert.pem
|
||||
```
|
||||
|
||||
Then seal a secret using the OpenFaaS CLI:
|
||||
|
||||
```bash
|
||||
$ faas-cli cloud seal --name alexellis-github \
|
||||
--literal hmac-secret=1234 --cert=pub-cert.pem
|
||||
```
|
||||
|
||||
You can then place the `secrets.yml` file in any public Git repo without others being able to read the contents.
|
||||
|
||||
When SealedSecrets is installed by ofc-bootstrap
|
||||
|
||||
The [scripts/export-sealed-secret-pubcert.sh](https://github.com/openfaas-incubator/ofc-bootstrap/blob/master/scripts/export-sealed-secret-pubcert.sh) does everything automatically.
|
||||
|
||||
### Environment variable overrides
|
||||
|
||||
* `OPENFAAS_TEMPLATE_URL` - to set the default URL to pull templates from
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
// Copyright (c) OpenFaaS Author(s). All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/openfaas/faas-cli/proxy"
|
||||
"github.com/openfaas/faas-cli/schema"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
namespace string
|
||||
name string
|
||||
literal *[]string
|
||||
outputFile string
|
||||
fromFile *[]string
|
||||
certFile string
|
||||
download bool
|
||||
downloadVersion string
|
||||
downloadTo string
|
||||
)
|
||||
|
||||
func init() {
|
||||
faasCmd.AddCommand(cloudCmd)
|
||||
|
||||
cloudSealCmd.Flags().StringVar(&name, "name", "", "Secret name")
|
||||
|
||||
cloudSealCmd.Flags().StringVarP(&namespace, "namespace", "n", "openfaas-fn", "Secret name")
|
||||
cloudSealCmd.Flags().StringVarP(&certFile, "cert", "c", "pub-cert.pem", "Filename of public certificate")
|
||||
|
||||
cloudSealCmd.Flags().StringVarP(&outputFile, "output-file", "o", "secrets.yml", "Output file for secrets")
|
||||
|
||||
cloudSealCmd.Flags().BoolVar(&download, "download", false, "Download the kubeseal binary required for this command, see also --download-version")
|
||||
cloudSealCmd.Flags().StringVar(&downloadVersion, "download-version", "", "Specify a kubeseal version to download")
|
||||
cloudSealCmd.Flags().StringVar(&downloadTo, "download-to", "", "Specify download path for kubeseal, leave empty for a temp dir")
|
||||
literal = cloudSealCmd.Flags().StringArrayP("literal", "l", []string{}, "Secret literal key-value data")
|
||||
|
||||
fromFile = cloudSealCmd.Flags().StringArrayP("from-file", "i", []string{}, "Read a secret from a from file")
|
||||
|
||||
cloudCmd.AddCommand(cloudSealCmd)
|
||||
}
|
||||
|
||||
var cloudCmd = &cobra.Command{
|
||||
Use: `cloud`,
|
||||
Short: "OpenFaaS Cloud commands",
|
||||
Long: "Commands for operating with OpenFaaS Cloud",
|
||||
}
|
||||
|
||||
var cloudSealCmd = &cobra.Command{
|
||||
Use: `seal [--name secret-name] [--literal k=v] [--from-file] [--namespace openfaas-fn] [--download]`,
|
||||
Short: "Seal a secret for usage with OpenFaaS Cloud",
|
||||
Example: ` faas-cli cloud seal --name alexellis-github --literal hmac-secret=c4488af0c158e8c
|
||||
faas-cli cloud seal --name alexellis-token --from-file api-key.txt
|
||||
faas-cli cloud seal --name alexellis-token --literal a=b --literal c=d --cert pub-cert.pem
|
||||
faas-cli cloud seal --download
|
||||
faas-cli cloud seal --download --download-version v0.9.5`,
|
||||
RunE: runCloudSeal,
|
||||
}
|
||||
|
||||
func runCloudSeal(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if download {
|
||||
return downloadKubeSeal()
|
||||
}
|
||||
|
||||
if len(name) == 0 {
|
||||
return fmt.Errorf("--name is required")
|
||||
}
|
||||
|
||||
fmt.Printf("Sealing secret: %s in namespace: %s\n", name, namespace)
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
enc := base64.StdEncoding
|
||||
|
||||
secret := schema.KubernetesSecret{
|
||||
ApiVersion: "v1",
|
||||
Kind: "Secret",
|
||||
Metadata: schema.KubernetesSecretMetadata{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: make(map[string]string),
|
||||
}
|
||||
|
||||
if literal != nil {
|
||||
args, _ := parseBuildArgs(*literal)
|
||||
|
||||
for k, v := range args {
|
||||
secret.Data[k] = enc.EncodeToString([]byte(v))
|
||||
}
|
||||
}
|
||||
|
||||
if fromFile != nil {
|
||||
for _, file := range *fromFile {
|
||||
bytesOut, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key := filepath.Base(file)
|
||||
secret.Data[key] = enc.EncodeToString(bytesOut)
|
||||
}
|
||||
}
|
||||
|
||||
sec, err := json.Marshal(secret)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(certFile); err != nil {
|
||||
return fmt.Errorf("unable to load public certificate %s", certFile)
|
||||
}
|
||||
|
||||
kubeseal := exec.Command("kubeseal", "--format=yaml", "--cert="+certFile)
|
||||
|
||||
stdin, stdinErr := kubeseal.StdinPipe()
|
||||
if stdinErr != nil {
|
||||
panic(stdinErr)
|
||||
}
|
||||
|
||||
stdin.Write(sec)
|
||||
stdin.Close()
|
||||
|
||||
out, err := kubeseal.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to start \"kubeseal\", check it is installed, error: %s", err.Error())
|
||||
}
|
||||
|
||||
writeErr := ioutil.WriteFile(outputFile, out, 0755)
|
||||
|
||||
if writeErr != nil {
|
||||
return fmt.Errorf("unable to write secret: %s to %s", name, outputFile)
|
||||
}
|
||||
|
||||
fmt.Printf("%s written.\n", outputFile)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadKubeSeal() error {
|
||||
releases := "https://github.com/bitnami-labs/sealed-secrets/releases/latest"
|
||||
|
||||
releaseVersion := downloadVersion
|
||||
if len(downloadVersion) == 0 {
|
||||
version, err := findRelease(releases)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
releaseVersion = version
|
||||
}
|
||||
|
||||
osVal := runtime.GOOS
|
||||
arch := runtime.GOARCH
|
||||
|
||||
if arch == "x86_64" {
|
||||
arch = "amd64"
|
||||
}
|
||||
|
||||
downloadURL := "https://github.com/bitnami/sealed-secrets/releases/download/" + releaseVersion + "/kubeseal-" + osVal + "-" + arch
|
||||
|
||||
fmt.Printf("Starting download of kubeseal %s, this could take a few moments.\n", releaseVersion)
|
||||
output, err := downloadBinary(http.DefaultClient, downloadURL, "kubeseal", downloadTo)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf(`Download completed, please run:
|
||||
|
||||
chmod +x %s
|
||||
%s --version
|
||||
sudo install %s /usr/local/bin/
|
||||
|
||||
`, output, output, output)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findRelease(url string) (string, error) {
|
||||
timeout := time.Second * 5
|
||||
client := proxy.MakeHTTPClient(&timeout, false)
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodHead, url, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
if res.StatusCode != 302 {
|
||||
return "", fmt.Errorf("incorrect status code: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
loc := res.Header.Get("Location")
|
||||
if len(loc) == 0 {
|
||||
return "", fmt.Errorf("unable to determine release of kubeseal")
|
||||
}
|
||||
version := loc[strings.LastIndex(loc, "/")+1:]
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func downloadBinary(client *http.Client, url, name, downloadTo string) (string, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("could not find release, http status code was %d, release may not exist for this architecture", res.StatusCode)
|
||||
}
|
||||
|
||||
var tempDir string
|
||||
if len(downloadTo) == 0 {
|
||||
tempDir = os.TempDir()
|
||||
} else {
|
||||
tempDir = downloadTo
|
||||
}
|
||||
|
||||
outputPath := path.Join(tempDir, name)
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
res, _ := ioutil.ReadAll(res.Body)
|
||||
|
||||
err := ioutil.WriteFile(outputPath, res, 0600)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return outputPath, nil
|
||||
}
|
||||
return "", fmt.Errorf("error downloading %s", url)
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/alexellis/arkade/pkg/get"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/openfaas/faas-cli/proxy"
|
||||
"github.com/openfaas/faas-cli/stack"
|
||||
@@ -50,23 +51,21 @@ This currently consists of the GitSHA from which the client was built.
|
||||
}
|
||||
|
||||
func runVersionE(cmd *cobra.Command, args []string) error {
|
||||
releases := "https://github.com/openfaas/faas-cli/releases/latest"
|
||||
|
||||
if shortVersion {
|
||||
fmt.Println(version.BuildVersion())
|
||||
return nil
|
||||
}
|
||||
|
||||
} else {
|
||||
printLogo()
|
||||
fmt.Printf(`CLI:
|
||||
printLogo()
|
||||
fmt.Printf(`CLI:
|
||||
commit: %s
|
||||
version: %s
|
||||
`, version.GitCommit, version.BuildVersion())
|
||||
printServerVersions()
|
||||
}
|
||||
printServerVersions()
|
||||
|
||||
if warnUpdate {
|
||||
version := version.Version
|
||||
latest, err := findRelease(releases)
|
||||
latest, err := get.FindGitHubRelease("openfaas", "faas-cli")
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find latest version online error: %s", err.Error())
|
||||
}
|
||||
|
||||
14
go.mod
14
go.mod
@@ -7,9 +7,10 @@ go 1.17
|
||||
// replace golang.org/x/sys => golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6
|
||||
|
||||
require (
|
||||
github.com/alexellis/arkade v0.0.0-20220922114024-7b7ade38cff9
|
||||
github.com/alexellis/go-execute v0.5.0
|
||||
github.com/alexellis/hmac v1.3.0
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible
|
||||
github.com/docker/docker v20.10.17+incompatible
|
||||
github.com/drone/envsubst v1.0.3
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
@@ -25,11 +26,20 @@ require (
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.0 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/gotestyourself/gotestyourself v1.4.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.6.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
|
||||
40
go.sum
40
go.sum
@@ -36,11 +36,16 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alexellis/arkade v0.0.0-20220922114024-7b7ade38cff9 h1:drPJV7B1oeWb84D9EV8EYpGPzY/mgFM0iMi2e+VXvII=
|
||||
github.com/alexellis/arkade v0.0.0-20220922114024-7b7ade38cff9/go.mod h1:KciGSe/OKQvM2yfesl5jelLr7wQIJBfLtUMUuGJ2xyo=
|
||||
github.com/alexellis/go-execute v0.5.0 h1:L8kgNlFzNbJov7jrInlaig7i6ZUSz/tYYmqvb8dyD0s=
|
||||
github.com/alexellis/go-execute v0.5.0/go.mod h1:AgHTcsCF9wrP0mMVTO8N+lFw1Biy71NybBOk8M+qgy8=
|
||||
github.com/alexellis/hmac v1.3.0 h1:DJl5wfuhwj2IjG9XRXzPY6bHZYrwrARFTotpxX3KS08=
|
||||
@@ -52,6 +57,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0 h1:3uouEsl32RL7gTiQsuaXD4Bzbfl5tGztXGUvXbs4O04=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0/go.mod h1:YjrevcBqadFDaGQKRdmZxTY42pXEqda48Ea3lt0K/BE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -60,12 +67,15 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
|
||||
github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -73,6 +83,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -179,12 +192,25 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
|
||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@@ -205,6 +231,8 @@ github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1t
|
||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nats-io/stan.go v0.9.0/go.mod h1:0jEuBXKauB1HHJswHM/lx05K48TJ1Yxj6VIfM4k+aB4=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/openfaas/faas-provider v0.18.6/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98=
|
||||
github.com/openfaas/faas-provider v0.19.0 h1:1dv4HDkWa9/yVkUll23/06y9lf8+tISOxYoHwBXZaJI=
|
||||
github.com/openfaas/faas-provider v0.19.0/go.mod h1:Farrp+9Med8LeK3aoYpqplMP8f5ebTILbCSLg2LPLZk=
|
||||
@@ -239,6 +267,9 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
@@ -247,8 +278,10 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -386,6 +419,7 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -410,7 +444,11 @@ golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME=
|
||||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -436,6 +474,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -565,6 +604,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0=
|
||||
gotest.tools v1.4.0/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
3
vendor/github.com/VividCortex/ewma/.gitignore
generated
vendored
Normal file
3
vendor/github.com/VividCortex/ewma/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
.*.sw?
|
||||
/coverage.txt
|
||||
3
vendor/github.com/VividCortex/ewma/.whitesource
generated
vendored
Normal file
3
vendor/github.com/VividCortex/ewma/.whitesource
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"settingsInheritedFrom": "VividCortex/whitesource-config@master"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2014 Simon Eskildsen
|
||||
Copyright (c) 2013 VividCortex
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
145
vendor/github.com/VividCortex/ewma/README.md
generated
vendored
Normal file
145
vendor/github.com/VividCortex/ewma/README.md
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
# EWMA
|
||||
|
||||
[](https://godoc.org/github.com/VividCortex/ewma)
|
||||

|
||||
[](https://codecov.io/gh/VividCortex/ewma)
|
||||
|
||||
This repo provides Exponentially Weighted Moving Average algorithms, or EWMAs for short, [based on our
|
||||
Quantifying Abnormal Behavior talk](https://vividcortex.com/blog/2013/07/23/a-fast-go-library-for-exponential-moving-averages/).
|
||||
|
||||
### Exponentially Weighted Moving Average
|
||||
|
||||
An exponentially weighted moving average is a way to continuously compute a type of
|
||||
average for a series of numbers, as the numbers arrive. After a value in the series is
|
||||
added to the average, its weight in the average decreases exponentially over time. This
|
||||
biases the average towards more recent data. EWMAs are useful for several reasons, chiefly
|
||||
their inexpensive computational and memory cost, as well as the fact that they represent
|
||||
the recent central tendency of the series of values.
|
||||
|
||||
The EWMA algorithm requires a decay factor, alpha. The larger the alpha, the more the average
|
||||
is biased towards recent history. The alpha must be between 0 and 1, and is typically
|
||||
a fairly small number, such as 0.04. We will discuss the choice of alpha later.
|
||||
|
||||
The algorithm works thus, in pseudocode:
|
||||
|
||||
1. Multiply the next number in the series by alpha.
|
||||
2. Multiply the current value of the average by 1 minus alpha.
|
||||
3. Add the result of steps 1 and 2, and store it as the new current value of the average.
|
||||
4. Repeat for each number in the series.
|
||||
|
||||
There are special-case behaviors for how to initialize the current value, and these vary
|
||||
between implementations. One approach is to start with the first value in the series;
|
||||
another is to average the first 10 or so values in the series using an arithmetic average,
|
||||
and then begin the incremental updating of the average. Each method has pros and cons.
|
||||
|
||||
It may help to look at it pictorially. Suppose the series has five numbers, and we choose
|
||||
alpha to be 0.50 for simplicity. Here's the series, with numbers in the neighborhood of 300.
|
||||
|
||||

|
||||
|
||||
Now let's take the moving average of those numbers. First we set the average to the value
|
||||
of the first number.
|
||||
|
||||

|
||||
|
||||
Next we multiply the next number by alpha, multiply the current value by 1-alpha, and add
|
||||
them to generate a new value.
|
||||
|
||||

|
||||
|
||||
This continues until we are done.
|
||||
|
||||

|
||||
|
||||
Notice how each of the values in the series decays by half each time a new value
|
||||
is added, and the top of the bars in the lower portion of the image represents the
|
||||
size of the moving average. It is a smoothed, or low-pass, average of the original
|
||||
series.
|
||||
|
||||
For further reading, see [Exponentially weighted moving average](http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) on wikipedia.
|
||||
|
||||
### Choosing Alpha
|
||||
|
||||
Consider a fixed-size sliding-window moving average (not an exponentially weighted moving average)
|
||||
that averages over the previous N samples. What is the average age of each sample? It is N/2.
|
||||
|
||||
Now suppose that you wish to construct a EWMA whose samples have the same average age. The formula
|
||||
to compute the alpha required for this is: alpha = 2/(N+1). Proof is in the book
|
||||
"Production and Operations Analysis" by Steven Nahmias.
|
||||
|
||||
So, for example, if you have a time-series with samples once per second, and you want to get the
|
||||
moving average over the previous minute, you should use an alpha of .032786885. This, by the way,
|
||||
is the constant alpha used for this repository's SimpleEWMA.
|
||||
|
||||
### Implementations
|
||||
|
||||
This repository contains two implementations of the EWMA algorithm, with different properties.
|
||||
|
||||
The implementations all conform to the MovingAverage interface, and the constructor returns
|
||||
that type.
|
||||
|
||||
Current implementations assume an implicit time interval of 1.0 between every sample added.
|
||||
That is, the passage of time is treated as though it's the same as the arrival of samples.
|
||||
If you need time-based decay when samples are not arriving precisely at set intervals, then
|
||||
this package will not support your needs at present.
|
||||
|
||||
#### SimpleEWMA
|
||||
|
||||
A SimpleEWMA is designed for low CPU and memory consumption. It **will** have different behavior than the VariableEWMA
|
||||
for multiple reasons. It has no warm-up period and it uses a constant
|
||||
decay. These properties let it use less memory. It will also behave
|
||||
differently when it's equal to zero, which is assumed to mean
|
||||
uninitialized, so if a value is likely to actually become zero over time,
|
||||
then any non-zero value will cause a sharp jump instead of a small change.
|
||||
|
||||
#### VariableEWMA
|
||||
|
||||
Unlike SimpleEWMA, this supports a custom age which must be stored, and thus uses more memory.
|
||||
It also has a "warmup" time when you start adding values to it. It will report a value of 0.0
|
||||
until you have added the required number of samples to it. It uses some memory to store the
|
||||
number of samples added to it. As a result it uses a little over twice the memory of SimpleEWMA.
|
||||
|
||||
## Usage
|
||||
|
||||
### API Documentation
|
||||
|
||||
View the GoDoc generated documentation [here](http://godoc.org/github.com/VividCortex/ewma).
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/VividCortex/ewma"
|
||||
|
||||
func main() {
|
||||
samples := [100]float64{
|
||||
4599, 5711, 4746, 4621, 5037, 4218, 4925, 4281, 5207, 5203, 5594, 5149,
|
||||
}
|
||||
|
||||
e := ewma.NewMovingAverage() //=> Returns a SimpleEWMA if called without params
|
||||
a := ewma.NewMovingAverage(5) //=> returns a VariableEWMA with a decay of 2 / (5 + 1)
|
||||
|
||||
for _, f := range samples {
|
||||
e.Add(f)
|
||||
a.Add(f)
|
||||
}
|
||||
|
||||
e.Value() //=> 13.577404704631077
|
||||
a.Value() //=> 1.5806140565521463e-12
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We only accept pull requests for minor fixes or improvements. This includes:
|
||||
|
||||
* Small bug fixes
|
||||
* Typos
|
||||
* Documentation or comments
|
||||
|
||||
Please open issues to discuss new features. Pull requests for new features will be rejected,
|
||||
so we recommend forking the repository and making changes in your fork for your use case.
|
||||
|
||||
## License
|
||||
|
||||
This repository is Copyright (c) 2013 VividCortex, Inc. All rights reserved.
|
||||
It is licensed under the MIT license. Please see the LICENSE file for applicable license terms.
|
||||
6
vendor/github.com/VividCortex/ewma/codecov.yml
generated
vendored
Normal file
6
vendor/github.com/VividCortex/ewma/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 15%
|
||||
patch: off
|
||||
126
vendor/github.com/VividCortex/ewma/ewma.go
generated
vendored
Normal file
126
vendor/github.com/VividCortex/ewma/ewma.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Package ewma implements exponentially weighted moving averages.
|
||||
package ewma
|
||||
|
||||
// Copyright (c) 2013 VividCortex, Inc. All rights reserved.
|
||||
// Please see the LICENSE file for applicable license terms.
|
||||
|
||||
const (
|
||||
// By default, we average over a one-minute period, which means the average
|
||||
// age of the metrics in the period is 30 seconds.
|
||||
AVG_METRIC_AGE float64 = 30.0
|
||||
|
||||
// The formula for computing the decay factor from the average age comes
|
||||
// from "Production and Operations Analysis" by Steven Nahmias.
|
||||
DECAY float64 = 2 / (float64(AVG_METRIC_AGE) + 1)
|
||||
|
||||
// For best results, the moving average should not be initialized to the
|
||||
// samples it sees immediately. The book "Production and Operations
|
||||
// Analysis" by Steven Nahmias suggests initializing the moving average to
|
||||
// the mean of the first 10 samples. Until the VariableEwma has seen this
|
||||
// many samples, it is not "ready" to be queried for the value of the
|
||||
// moving average. This adds some memory cost.
|
||||
WARMUP_SAMPLES uint8 = 10
|
||||
)
|
||||
|
||||
// MovingAverage is the interface that computes a moving average over a time-
|
||||
// series stream of numbers. The average may be over a window or exponentially
|
||||
// decaying.
|
||||
type MovingAverage interface {
|
||||
Add(float64)
|
||||
Value() float64
|
||||
Set(float64)
|
||||
}
|
||||
|
||||
// NewMovingAverage constructs a MovingAverage that computes an average with the
|
||||
// desired characteristics in the moving window or exponential decay. If no
|
||||
// age is given, it constructs a default exponentially weighted implementation
|
||||
// that consumes minimal memory. The age is related to the decay factor alpha
|
||||
// by the formula given for the DECAY constant. It signifies the average age
|
||||
// of the samples as time goes to infinity.
|
||||
func NewMovingAverage(age ...float64) MovingAverage {
|
||||
if len(age) == 0 || age[0] == AVG_METRIC_AGE {
|
||||
return new(SimpleEWMA)
|
||||
}
|
||||
return &VariableEWMA{
|
||||
decay: 2 / (age[0] + 1),
|
||||
}
|
||||
}
|
||||
|
||||
// A SimpleEWMA represents the exponentially weighted moving average of a
|
||||
// series of numbers. It WILL have different behavior than the VariableEWMA
|
||||
// for multiple reasons. It has no warm-up period and it uses a constant
|
||||
// decay. These properties let it use less memory. It will also behave
|
||||
// differently when it's equal to zero, which is assumed to mean
|
||||
// uninitialized, so if a value is likely to actually become zero over time,
|
||||
// then any non-zero value will cause a sharp jump instead of a small change.
|
||||
// However, note that this takes a long time, and the value may just
|
||||
// decays to a stable value that's close to zero, but which won't be mistaken
|
||||
// for uninitialized. See http://play.golang.org/p/litxBDr_RC for example.
|
||||
type SimpleEWMA struct {
|
||||
// The current value of the average. After adding with Add(), this is
|
||||
// updated to reflect the average of all values seen thus far.
|
||||
value float64
|
||||
}
|
||||
|
||||
// Add adds a value to the series and updates the moving average.
|
||||
func (e *SimpleEWMA) Add(value float64) {
|
||||
if e.value == 0 { // this is a proxy for "uninitialized"
|
||||
e.value = value
|
||||
} else {
|
||||
e.value = (value * DECAY) + (e.value * (1 - DECAY))
|
||||
}
|
||||
}
|
||||
|
||||
// Value returns the current value of the moving average.
|
||||
func (e *SimpleEWMA) Value() float64 {
|
||||
return e.value
|
||||
}
|
||||
|
||||
// Set sets the EWMA's value.
|
||||
func (e *SimpleEWMA) Set(value float64) {
|
||||
e.value = value
|
||||
}
|
||||
|
||||
// VariableEWMA represents the exponentially weighted moving average of a series of
|
||||
// numbers. Unlike SimpleEWMA, it supports a custom age, and thus uses more memory.
|
||||
type VariableEWMA struct {
|
||||
// The multiplier factor by which the previous samples decay.
|
||||
decay float64
|
||||
// The current value of the average.
|
||||
value float64
|
||||
// The number of samples added to this instance.
|
||||
count uint8
|
||||
}
|
||||
|
||||
// Add adds a value to the series and updates the moving average.
|
||||
func (e *VariableEWMA) Add(value float64) {
|
||||
switch {
|
||||
case e.count < WARMUP_SAMPLES:
|
||||
e.count++
|
||||
e.value += value
|
||||
case e.count == WARMUP_SAMPLES:
|
||||
e.count++
|
||||
e.value = e.value / float64(WARMUP_SAMPLES)
|
||||
e.value = (value * e.decay) + (e.value * (1 - e.decay))
|
||||
default:
|
||||
e.value = (value * e.decay) + (e.value * (1 - e.decay))
|
||||
}
|
||||
}
|
||||
|
||||
// Value returns the current value of the average, or 0.0 if the series hasn't
|
||||
// warmed up yet.
|
||||
func (e *VariableEWMA) Value() float64 {
|
||||
if e.count <= WARMUP_SAMPLES {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return e.value
|
||||
}
|
||||
|
||||
// Set sets the EWMA's value.
|
||||
func (e *VariableEWMA) Set(value float64) {
|
||||
e.value = value
|
||||
if e.count <= WARMUP_SAMPLES {
|
||||
e.count = WARMUP_SAMPLES + 1
|
||||
}
|
||||
}
|
||||
21
vendor/github.com/alexellis/arkade/LICENSE
generated
vendored
Normal file
21
vendor/github.com/alexellis/arkade/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Alex Ellis
|
||||
|
||||
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.
|
||||
132
vendor/github.com/alexellis/arkade/pkg/archive/untar.go
generated
vendored
Normal file
132
vendor/github.com/alexellis/arkade/pkg/archive/untar.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Untar reads the gzip-compressed tar file from r and writes it into dir.
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// AE: Edited on 2019-10-11 to remove support for nested folders when un-taring
|
||||
// so that all files are placed in the same target directory
|
||||
func Untar(r io.Reader, dir string, quiet bool) error {
|
||||
return untar(r, dir, quiet)
|
||||
}
|
||||
|
||||
func untar(r io.Reader, dir string, quiet bool) (err error) {
|
||||
t0 := time.Now()
|
||||
nFiles := 0
|
||||
madeDir := map[string]bool{}
|
||||
defer func() {
|
||||
td := time.Since(t0)
|
||||
|
||||
if err == nil {
|
||||
if !quiet {
|
||||
log.Printf("extracted tarball into %s: %d files, %d dirs (%v)", dir, nFiles, len(madeDir), td)
|
||||
}
|
||||
} else {
|
||||
log.Printf("error extracting tarball into %s after %d files, %d dirs, %v: %v", dir, nFiles, len(madeDir), td, err)
|
||||
}
|
||||
|
||||
}()
|
||||
zr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("requires gzip-compressed body: %v", err)
|
||||
}
|
||||
tr := tar.NewReader(zr)
|
||||
loggedChtimesError := false
|
||||
for {
|
||||
f, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("tar reading error: %v", err)
|
||||
return fmt.Errorf("tar error: %v", err)
|
||||
}
|
||||
if !validRelPath(f.Name) {
|
||||
return fmt.Errorf("tar contained invalid name error %q", f.Name)
|
||||
}
|
||||
baseFile := filepath.Base(f.Name)
|
||||
abs := path.Join(dir, baseFile)
|
||||
if !quiet {
|
||||
fmt.Printf("Extracting: %s to\t%s\n", f.Name, abs)
|
||||
}
|
||||
|
||||
fi := f.FileInfo()
|
||||
mode := fi.Mode()
|
||||
switch {
|
||||
case mode.IsDir():
|
||||
|
||||
break
|
||||
|
||||
case mode.IsRegular():
|
||||
|
||||
wf, err := os.OpenFile(abs, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode.Perm())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := io.Copy(wf, tr)
|
||||
if closeErr := wf.Close(); closeErr != nil && err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to %s: %v", abs, err)
|
||||
}
|
||||
if n != f.Size {
|
||||
return fmt.Errorf("only wrote %d bytes to %s; expected %d", n, abs, f.Size)
|
||||
}
|
||||
modTime := f.ModTime
|
||||
if modTime.After(t0) {
|
||||
// Clamp modtimes at system time. See
|
||||
// golang.org/issue/19062 when clock on
|
||||
// buildlet was behind the gitmirror server
|
||||
// doing the git-archive.
|
||||
modTime = t0
|
||||
}
|
||||
if !modTime.IsZero() {
|
||||
if err := os.Chtimes(abs, modTime, modTime); err != nil && !loggedChtimesError {
|
||||
// benign error. Gerrit doesn't even set the
|
||||
// modtime in these, and we don't end up relying
|
||||
// on it anywhere (the gomote push command relies
|
||||
// on digests only), so this is a little pointless
|
||||
// for now.
|
||||
log.Printf("error changing modtime: %v (further Chtimes errors suppressed)", err)
|
||||
loggedChtimesError = true // once is enough
|
||||
}
|
||||
}
|
||||
nFiles++
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validRelativeDir(dir string) bool {
|
||||
if strings.Contains(dir, `\`) || path.IsAbs(dir) {
|
||||
return false
|
||||
}
|
||||
dir = path.Clean(dir)
|
||||
if strings.HasPrefix(dir, "../") || strings.HasSuffix(dir, "/..") || dir == ".." {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func validRelPath(p string) bool {
|
||||
if p == "" || strings.Contains(p, `\`) || strings.HasPrefix(p, "/") || strings.Contains(p, "../") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
120
vendor/github.com/alexellis/arkade/pkg/archive/untar_nested.go
generated
vendored
Normal file
120
vendor/github.com/alexellis/arkade/pkg/archive/untar_nested.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UntarNested reads the gzip-compressed tar file from r and writes it into dir.
|
||||
// Copyright 2017 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.
|
||||
func UntarNested(r io.Reader, dir string) error {
|
||||
return untarNested(r, dir)
|
||||
}
|
||||
|
||||
func untarNested(r io.Reader, dir string) (err error) {
|
||||
t0 := time.Now()
|
||||
nFiles := 0
|
||||
madeDir := map[string]bool{}
|
||||
defer func() {
|
||||
td := time.Since(t0)
|
||||
if err == nil {
|
||||
log.Printf("extracted tarball into %s: %d files, %d dirs (%v)", dir, nFiles, len(madeDir), td)
|
||||
} else {
|
||||
log.Printf("error extracting tarball into %s after %d files, %d dirs, %v: %v", dir, nFiles, len(madeDir), td, err)
|
||||
}
|
||||
}()
|
||||
zr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("requires gzip-compressed body: %v", err)
|
||||
}
|
||||
tr := tar.NewReader(zr)
|
||||
loggedChtimesError := false
|
||||
for {
|
||||
f, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("tar reading error: %v", err)
|
||||
return fmt.Errorf("tar error: %v", err)
|
||||
}
|
||||
if !validRelPath(f.Name) {
|
||||
return fmt.Errorf("tar contained invalid name error %q", f.Name)
|
||||
}
|
||||
rel := filepath.FromSlash(f.Name)
|
||||
abs := filepath.Join(dir, rel)
|
||||
|
||||
fi := f.FileInfo()
|
||||
mode := fi.Mode()
|
||||
switch {
|
||||
case mode.IsRegular():
|
||||
// Make the directory. This is redundant because it should
|
||||
// already be made by a directory entry in the tar
|
||||
// beforehand. Thus, don't check for errors; the next
|
||||
// write will fail with the same error.
|
||||
dir := filepath.Dir(abs)
|
||||
if !madeDir[dir] {
|
||||
if err := os.MkdirAll(filepath.Dir(abs), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
madeDir[dir] = true
|
||||
}
|
||||
wf, err := os.OpenFile(abs, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode.Perm())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := io.Copy(wf, tr)
|
||||
if closeErr := wf.Close(); closeErr != nil && err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to %s: %v", abs, err)
|
||||
}
|
||||
if n != f.Size {
|
||||
return fmt.Errorf("only wrote %d bytes to %s; expected %d", n, abs, f.Size)
|
||||
}
|
||||
modTime := f.ModTime
|
||||
if modTime.After(t0) {
|
||||
// Clamp modtimes at system time. See
|
||||
// golang.org/issue/19062 when clock on
|
||||
// buildlet was behind the gitmirror server
|
||||
// doing the git-archive.
|
||||
modTime = t0
|
||||
}
|
||||
if !modTime.IsZero() {
|
||||
if err := os.Chtimes(abs, modTime, modTime); err != nil && !loggedChtimesError {
|
||||
// benign error. Gerrit doesn't even set the
|
||||
// modtime in these, and we don't end up relying
|
||||
// on it anywhere (the gomote push command relies
|
||||
// on digests only), so this is a little pointless
|
||||
// for now.
|
||||
log.Printf("error changing modtime: %v (further Chtimes errors suppressed)", err)
|
||||
loggedChtimesError = true // once is enough
|
||||
}
|
||||
}
|
||||
nFiles++
|
||||
case mode.IsDir():
|
||||
if err := os.MkdirAll(abs, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
madeDir[abs] = true
|
||||
// Introduced via
|
||||
// https://github.com/alexellis/arkade/pull/675/files
|
||||
case os.ModeSymlink != 0:
|
||||
if err := os.Symlink(f.Linkname, abs); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("tar file entry %s contained unsupported file type %v", f.Name, mode)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
100
vendor/github.com/alexellis/arkade/pkg/archive/unzip.go
generated
vendored
Normal file
100
vendor/github.com/alexellis/arkade/pkg/archive/unzip.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) arkade author(s) 2022. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Unzip reads the compressed zip file from reader and writes it into dir.
|
||||
// Unzip works similar to Untar where support for nested folders is removed
|
||||
// so that all files are placed in the same target directory
|
||||
func Unzip(reader io.ReaderAt, size int64, dir string, quiet bool) error {
|
||||
zipReader, err := zip.NewReader(reader, size)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating zip reader: %s", err)
|
||||
}
|
||||
|
||||
return unzip(*zipReader, dir, quiet)
|
||||
}
|
||||
|
||||
func unzip(r zip.Reader, dir string, quiet bool) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
nFiles := 0
|
||||
madeDir := map[string]bool{}
|
||||
defer func() {
|
||||
td := time.Since(t0)
|
||||
if err == nil {
|
||||
if !quiet {
|
||||
log.Printf("extracted zip into %s: %d files, %d dirs (%v)", dir, nFiles, len(madeDir), td)
|
||||
}
|
||||
} else {
|
||||
log.Printf("error extracting zip into %s after %d files, %d dirs, %v: %v", dir, nFiles, len(madeDir), td, err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Closure to address file descriptors issue with all the deferred .Close() methods
|
||||
extractAndWriteFile := func(f *zip.File) error {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := rc.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
baseFile := filepath.Base(f.Name)
|
||||
abs := path.Join(dir, baseFile)
|
||||
|
||||
if !quiet {
|
||||
fmt.Printf("Extracting: %s\n", abs)
|
||||
}
|
||||
|
||||
fi := f.FileInfo()
|
||||
mode := fi.Mode()
|
||||
|
||||
switch {
|
||||
case mode.IsDir():
|
||||
break
|
||||
case mode.IsRegular():
|
||||
f, err := os.OpenFile(abs, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(f, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
}
|
||||
nFiles++
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, f := range r.File {
|
||||
err := extractAndWriteFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
82
vendor/github.com/alexellis/arkade/pkg/config/config.go
generated
vendored
Normal file
82
vendor/github.com/alexellis/arkade/pkg/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) arkade author(s) 2022. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetUserDir() string {
|
||||
home := os.Getenv("HOME")
|
||||
root := fmt.Sprintf("%s/.arkade/", home)
|
||||
return root
|
||||
}
|
||||
|
||||
func InitUserDir() (string, error) {
|
||||
home := os.Getenv("HOME")
|
||||
root := fmt.Sprintf("%s/.arkade/", home)
|
||||
|
||||
if len(home) == 0 {
|
||||
return home, fmt.Errorf("env-var HOME, not set")
|
||||
}
|
||||
|
||||
binPath := path.Join(root, "/bin/")
|
||||
err := os.MkdirAll(binPath, 0700)
|
||||
if err != nil {
|
||||
return binPath, err
|
||||
}
|
||||
|
||||
helmPath := path.Join(root, "/.helm/")
|
||||
helmErr := os.MkdirAll(helmPath, 0700)
|
||||
if helmErr != nil {
|
||||
return helmPath, helmErr
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func GetDefaultKubeconfig() string {
|
||||
kubeConfigPath := path.Join(os.Getenv("HOME"), ".kube/config")
|
||||
|
||||
if val, ok := os.LookupEnv("KUBECONFIG"); ok {
|
||||
kubeConfigPath = val
|
||||
}
|
||||
|
||||
return kubeConfigPath
|
||||
}
|
||||
|
||||
func MergeFlags(existingMap map[string]string, setOverrides []string) error {
|
||||
for _, setOverride := range setOverrides {
|
||||
// Limit the number of parts to 2 to keep `=` characters in the value.
|
||||
flag := strings.SplitN(setOverride, "=", 2)
|
||||
if len(flag) != 2 {
|
||||
return fmt.Errorf("incorrect format for custom flag `%s`", setOverride)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(flag[1], "'") && strings.HasSuffix(flag[1], "'") {
|
||||
flag[1] = flag[1][1 : len(flag[1])-1]
|
||||
}
|
||||
|
||||
existingMap[flag[0]] = flag[1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetKubeconfig(kubeconfigPath string) error {
|
||||
// Favour explicitly set kubeconfig
|
||||
if len(kubeconfigPath) > 0 {
|
||||
err := os.Setenv("KUBECONFIG", kubeconfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
kubeconfig := GetDefaultKubeconfig()
|
||||
|
||||
fmt.Printf("Using Kubeconfig: %s\n", kubeconfig)
|
||||
return nil
|
||||
}
|
||||
44
vendor/github.com/alexellis/arkade/pkg/env/env.go
generated
vendored
Normal file
44
vendor/github.com/alexellis/arkade/pkg/env/env.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) arkade author(s) 2022. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
package env
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
execute "github.com/alexellis/go-execute/pkg/v1"
|
||||
)
|
||||
|
||||
// GetClientArch returns a pair of arch and os
|
||||
func GetClientArch() (arch string, os string) {
|
||||
task := execute.ExecTask{Command: "uname", Args: []string{"-m"}, StreamStdio: false}
|
||||
res, err := task.Execute()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
archResult := strings.TrimSpace(res.Stdout)
|
||||
|
||||
taskOS := execute.ExecTask{Command: "uname", Args: []string{"-s"}, StreamStdio: false}
|
||||
resOS, errOS := taskOS.Execute()
|
||||
if errOS != nil {
|
||||
log.Println(errOS)
|
||||
}
|
||||
|
||||
osResult := strings.TrimSpace(resOS.Stdout)
|
||||
|
||||
return archResult, osResult
|
||||
}
|
||||
|
||||
func LocalBinary(name, subdir string) string {
|
||||
home := os.Getenv("HOME")
|
||||
val := path.Join(home, ".arkade/bin/")
|
||||
if len(subdir) > 0 {
|
||||
val = path.Join(val, subdir)
|
||||
}
|
||||
|
||||
return path.Join(val, name)
|
||||
}
|
||||
227
vendor/github.com/alexellis/arkade/pkg/get/download.go
generated
vendored
Normal file
227
vendor/github.com/alexellis/arkade/pkg/get/download.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
package get
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/alexellis/arkade/pkg/archive"
|
||||
"github.com/alexellis/arkade/pkg/config"
|
||||
"github.com/alexellis/arkade/pkg/env"
|
||||
"github.com/cheggaaa/pb/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
DownloadTempDir = iota
|
||||
DownloadArkadeDir = iota
|
||||
)
|
||||
|
||||
func Download(tool *Tool, arch, operatingSystem, version string, downloadMode int, displayProgress, quiet bool) (string, string, error) {
|
||||
|
||||
downloadURL, err := GetDownloadURL(tool,
|
||||
strings.ToLower(operatingSystem),
|
||||
strings.ToLower(arch),
|
||||
version, quiet)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if !quiet {
|
||||
fmt.Printf("Downloading: %s\n", downloadURL)
|
||||
}
|
||||
|
||||
outFilePath, err := downloadFile(downloadURL, displayProgress)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if !quiet {
|
||||
fmt.Printf("%s written.\n", outFilePath)
|
||||
}
|
||||
|
||||
if isArchive, err := tool.IsArchive(quiet); isArchive {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
outPath, err := decompress(tool, downloadURL, outFilePath, operatingSystem, arch, version, quiet)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
outFilePath = outPath
|
||||
if !quiet {
|
||||
log.Printf("Extracted: %s", outFilePath)
|
||||
}
|
||||
}
|
||||
|
||||
finalName := tool.Name
|
||||
if strings.Contains(strings.ToLower(operatingSystem), "mingw") && tool.NoExtension == false {
|
||||
finalName = finalName + ".exe"
|
||||
}
|
||||
|
||||
if downloadMode == DownloadArkadeDir {
|
||||
_, err := config.InitUserDir()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
localPath := env.LocalBinary(finalName, "")
|
||||
|
||||
if !quiet {
|
||||
log.Printf("Copying %s to %s\n", outFilePath, localPath)
|
||||
}
|
||||
_, err = CopyFile(outFilePath, localPath)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
outFilePath = localPath
|
||||
}
|
||||
|
||||
return outFilePath, finalName, nil
|
||||
}
|
||||
|
||||
func DownloadFileP(downloadURL string, displayProgress bool) (string, error) {
|
||||
return downloadFile(downloadURL, displayProgress)
|
||||
}
|
||||
|
||||
func downloadFile(downloadURL string, displayProgress bool) (string, error) {
|
||||
res, err := http.DefaultClient.Get(downloadURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("incorrect status for downloading tool: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
_, fileName := path.Split(downloadURL)
|
||||
tmp := os.TempDir()
|
||||
outFilePath := path.Join(tmp, fileName)
|
||||
wrappedReader := withProgressBar(res.Body, int(res.ContentLength), displayProgress)
|
||||
out, err := os.Create(outFilePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
defer wrappedReader.Close()
|
||||
|
||||
if _, err := io.Copy(out, wrappedReader); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return outFilePath, nil
|
||||
}
|
||||
|
||||
func CopyFile(src, dst string) (int64, error) {
|
||||
return CopyFileP(src, dst, 0700)
|
||||
}
|
||||
|
||||
func CopyFileP(src, dst string, permMode int) (int64, error) {
|
||||
sourceFileStat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !sourceFileStat.Mode().IsRegular() {
|
||||
return 0, fmt.Errorf("%s is not a regular file", src)
|
||||
}
|
||||
|
||||
source, err := os.Open(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
destination, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(permMode))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer destination.Close()
|
||||
nBytes, err := io.Copy(destination, source)
|
||||
return nBytes, err
|
||||
}
|
||||
|
||||
func withProgressBar(r io.ReadCloser, length int, displayProgress bool) io.ReadCloser {
|
||||
if !displayProgress {
|
||||
return r
|
||||
}
|
||||
|
||||
bar := pb.Simple.New(length).Start()
|
||||
return bar.NewProxyReader(r)
|
||||
}
|
||||
|
||||
func decompress(tool *Tool, downloadURL, outFilePath, operatingSystem, arch, version string, quiet bool) (string, error) {
|
||||
|
||||
archiveFile, err := os.Open(outFilePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
outFilePathDir := filepath.Dir(outFilePath)
|
||||
if len(tool.BinaryTemplate) == 0 && len(tool.URLTemplate) > 0 {
|
||||
outFilePath = path.Join(outFilePathDir, tool.Name)
|
||||
} else if len(tool.BinaryTemplate) > 0 && len(tool.URLTemplate) == 0 &&
|
||||
(!strings.Contains(tool.BinaryTemplate, "tar.gz") &&
|
||||
!strings.Contains(tool.BinaryTemplate, "zip") &&
|
||||
!strings.Contains(tool.BinaryTemplate, "tgz")) {
|
||||
fileName, err := GetBinaryName(tool,
|
||||
strings.ToLower(operatingSystem),
|
||||
strings.ToLower(arch),
|
||||
version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
outFilePath = path.Join(outFilePathDir, fileName)
|
||||
} else if len(tool.BinaryTemplate) > 0 && len(tool.URLTemplate) > 0 {
|
||||
fileName, err := GetBinaryName(tool,
|
||||
strings.ToLower(operatingSystem),
|
||||
strings.ToLower(arch),
|
||||
version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
outFilePath = path.Join(outFilePathDir, fileName)
|
||||
|
||||
} else {
|
||||
outFilePath = path.Join(outFilePathDir, tool.Name)
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(operatingSystem), "mingw") && tool.NoExtension == false {
|
||||
outFilePath += ".exe"
|
||||
}
|
||||
|
||||
forceQuiet := true
|
||||
|
||||
if strings.HasSuffix(downloadURL, "tar.gz") || strings.HasSuffix(downloadURL, "tgz") {
|
||||
if err := archive.Untar(archiveFile, outFilePathDir, forceQuiet); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else if strings.HasSuffix(downloadURL, "zip") {
|
||||
fInfo, err := archiveFile.Stat()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !quiet {
|
||||
fmt.Printf("Name: %s, size: %d", fInfo.Name(), fInfo.Size())
|
||||
}
|
||||
|
||||
if err := archive.Unzip(archiveFile, fInfo.Size(), outFilePathDir, forceQuiet); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return outFilePath, nil
|
||||
}
|
||||
427
vendor/github.com/alexellis/arkade/pkg/get/get.go
generated
vendored
Normal file
427
vendor/github.com/alexellis/arkade/pkg/get/get.go
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
package get
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/alexellis/arkade/pkg/env"
|
||||
)
|
||||
|
||||
var supportedOS = [...]string{"linux", "darwin", "ming"}
|
||||
var supportedArchitectures = [...]string{"x86_64", "arm", "amd64", "armv6l", "armv7l", "arm64", "aarch64"}
|
||||
|
||||
// githubTimeout expanded from the original 5 seconds due to #693
|
||||
var githubTimeout = time.Second * 10
|
||||
|
||||
// Tool describes how to download a CLI tool from a binary
|
||||
// release - whether a single binary, or an archive.
|
||||
type Tool struct {
|
||||
// The name of the tool for download
|
||||
Name string
|
||||
|
||||
// Repo is a GitHub repo, when no repo exists, use the same
|
||||
// as the name.
|
||||
Repo string
|
||||
|
||||
// Owner is the name of the GitHub account, when no account
|
||||
// exists, use the vendor name lowercase.
|
||||
Owner string
|
||||
|
||||
// Version pinned or left empty to pull the latest release
|
||||
// if any only if only BinaryTemplate is specified.
|
||||
Version string
|
||||
|
||||
// Description of what the tool is used for.
|
||||
Description string
|
||||
|
||||
// URLTemplate specifies a Go template for the download URL
|
||||
// override the OS, architecture and extension
|
||||
// All whitespace will be trimmed/
|
||||
URLTemplate string
|
||||
|
||||
// The binary template can be used when downloading GitHub
|
||||
// It assumes that the only part of the URL needing to be
|
||||
// templated is the binary name on a standard GitHub download
|
||||
// URL.
|
||||
BinaryTemplate string
|
||||
|
||||
// NoExtension is required for tooling such as kubectx
|
||||
// which at time of writing is a bash script.
|
||||
NoExtension bool
|
||||
}
|
||||
|
||||
type ToolLocal struct {
|
||||
Name string
|
||||
Path string
|
||||
}
|
||||
|
||||
var templateFuncs = map[string]interface{}{
|
||||
"HasPrefix": func(s, prefix string) bool { return strings.HasPrefix(s, prefix) },
|
||||
}
|
||||
|
||||
func (tool Tool) IsArchive(quiet bool) (bool, error) {
|
||||
arch, operatingSystem := env.GetClientArch()
|
||||
version := ""
|
||||
|
||||
downloadURL, err := GetDownloadURL(&tool, strings.ToLower(operatingSystem), strings.ToLower(arch), version, quiet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return strings.HasSuffix(downloadURL, "tar.gz") ||
|
||||
strings.HasSuffix(downloadURL, "zip") ||
|
||||
strings.HasSuffix(downloadURL, "tgz"), nil
|
||||
}
|
||||
|
||||
// GetDownloadURL fetches the download URL for a release of a tool
|
||||
// for a given os, architecture and version
|
||||
func GetDownloadURL(tool *Tool, os, arch, version string, quiet bool) (string, error) {
|
||||
ver := getToolVersion(tool, version)
|
||||
|
||||
dlURL, err := tool.GetURL(os, arch, ver, quiet)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dlURL, nil
|
||||
}
|
||||
|
||||
func getToolVersion(tool *Tool, version string) string {
|
||||
ver := tool.Version
|
||||
if len(version) > 0 {
|
||||
ver = version
|
||||
}
|
||||
|
||||
return ver
|
||||
}
|
||||
|
||||
func (tool Tool) Head(uri string) (int, string, http.Header, error) {
|
||||
req, err := http.NewRequest(http.MethodHead, uri, nil)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, "", nil, err
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, "", nil, err
|
||||
}
|
||||
|
||||
var body string
|
||||
if res.Body != nil {
|
||||
b, _ := ioutil.ReadAll(res.Body)
|
||||
body = string(b)
|
||||
}
|
||||
|
||||
return res.StatusCode, body, res.Header, nil
|
||||
}
|
||||
|
||||
func (tool Tool) GetURL(os, arch, version string, quiet bool) (string, error) {
|
||||
|
||||
if len(version) == 0 &&
|
||||
(len(tool.URLTemplate) == 0 || strings.Contains(tool.URLTemplate, "https://github.com/")) {
|
||||
if !quiet {
|
||||
log.Printf("Looking up version for %s", tool.Name)
|
||||
}
|
||||
|
||||
v, err := FindGitHubRelease(tool.Owner, tool.Repo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !quiet {
|
||||
log.Printf("Found: %s", v)
|
||||
}
|
||||
version = v
|
||||
}
|
||||
|
||||
if len(tool.URLTemplate) > 0 {
|
||||
return getByDownloadTemplate(tool, os, arch, version)
|
||||
}
|
||||
|
||||
return getURLByGithubTemplate(tool, os, arch, version)
|
||||
}
|
||||
|
||||
func getURLByGithubTemplate(tool Tool, os, arch, version string) (string, error) {
|
||||
|
||||
var err error
|
||||
t := template.New(tool.Name + "binary")
|
||||
t = t.Funcs(templateFuncs)
|
||||
t, err = t.Parse(tool.BinaryTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
pref := map[string]string{
|
||||
"OS": os,
|
||||
"Arch": arch,
|
||||
"Name": tool.Name,
|
||||
"Version": version,
|
||||
"VersionNumber": strings.TrimPrefix(version, "v"),
|
||||
}
|
||||
|
||||
err = t.Execute(&buf, pref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
downloadName := strings.TrimSpace(buf.String())
|
||||
|
||||
return getBinaryURL(tool.Owner, tool.Repo, version, downloadName), nil
|
||||
}
|
||||
|
||||
func FindGitHubRelease(owner, repo string) (string, error) {
|
||||
url := fmt.Sprintf("https://github.com/%s/%s/releases/latest", owner, repo)
|
||||
|
||||
client := makeHTTPClient(&githubTimeout, false)
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodHead, url, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
if res.StatusCode != 302 {
|
||||
return "", fmt.Errorf("incorrect status code: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
loc := res.Header.Get("Location")
|
||||
if len(loc) == 0 {
|
||||
return "", fmt.Errorf("unable to determine release of tool")
|
||||
}
|
||||
|
||||
version := loc[strings.LastIndex(loc, "/")+1:]
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func getBinaryURL(owner, repo, version, downloadName string) string {
|
||||
if in := strings.Index(downloadName, "/"); in > -1 {
|
||||
return fmt.Sprintf(
|
||||
"https://github.com/%s/%s/releases/download/%s",
|
||||
owner, repo, downloadName)
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"https://github.com/%s/%s/releases/download/%s/%s",
|
||||
owner, repo, version, downloadName)
|
||||
}
|
||||
|
||||
func getByDownloadTemplate(tool Tool, os, arch, version string) (string, error) {
|
||||
var err error
|
||||
t := template.New(tool.Name)
|
||||
t = t.Funcs(templateFuncs)
|
||||
t, err = t.Parse(tool.URLTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
inputs := map[string]string{
|
||||
"OS": os,
|
||||
"Arch": arch,
|
||||
"Version": version,
|
||||
"VersionNumber": strings.TrimPrefix(version, "v"),
|
||||
"Repo": tool.Repo,
|
||||
"Owner": tool.Owner,
|
||||
"Name": tool.Name,
|
||||
}
|
||||
|
||||
if err := t.Execute(&buf, inputs); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res := strings.TrimSpace(buf.String())
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// makeHTTPClient makes a HTTP client with good defaults for timeouts.
|
||||
func makeHTTPClient(timeout *time.Duration, tlsInsecure bool) http.Client {
|
||||
return makeHTTPClientWithDisableKeepAlives(timeout, tlsInsecure, false)
|
||||
}
|
||||
|
||||
// makeHTTPClientWithDisableKeepAlives makes a HTTP client with good defaults for timeouts.
|
||||
func makeHTTPClientWithDisableKeepAlives(timeout *time.Duration, tlsInsecure bool, disableKeepAlives bool) http.Client {
|
||||
client := http.Client{}
|
||||
|
||||
if timeout != nil || tlsInsecure {
|
||||
tr := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DisableKeepAlives: disableKeepAlives,
|
||||
}
|
||||
|
||||
if timeout != nil {
|
||||
client.Timeout = *timeout
|
||||
tr.DialContext = (&net.Dialer{
|
||||
Timeout: *timeout,
|
||||
}).DialContext
|
||||
|
||||
tr.IdleConnTimeout = 120 * time.Millisecond
|
||||
tr.ExpectContinueTimeout = 1500 * time.Millisecond
|
||||
}
|
||||
|
||||
if tlsInsecure {
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: tlsInsecure}
|
||||
}
|
||||
|
||||
tr.DisableKeepAlives = disableKeepAlives
|
||||
|
||||
client.Transport = tr
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// GetBinaryName returns the name of a binary for the given tool or an
|
||||
// error if the tool's template cannot be parsed or executed.
|
||||
func GetBinaryName(tool *Tool, os, arch, version string) (string, error) {
|
||||
if len(tool.BinaryTemplate) > 0 {
|
||||
var err error
|
||||
t := template.New(tool.Name + "_binaryname")
|
||||
t = t.Funcs(templateFuncs)
|
||||
|
||||
t, err = t.Parse(tool.BinaryTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
ver := getToolVersion(tool, version)
|
||||
if err := t.Execute(&buf, map[string]string{
|
||||
"OS": os,
|
||||
"Arch": arch,
|
||||
"Name": tool.Name,
|
||||
"Version": ver,
|
||||
"VersionNumber": strings.TrimPrefix(ver, "v"),
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res := strings.TrimSpace(buf.String())
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return "", errors.New("BinaryTemplate is not set")
|
||||
}
|
||||
|
||||
// GetDownloadURLs generates a list of URL for each tool, for download
|
||||
func GetDownloadURLs(tools Tools, toolArgs []string, version string) (Tools, error) {
|
||||
arkadeTools := []Tool{}
|
||||
|
||||
for _, arg := range toolArgs {
|
||||
name := arg
|
||||
|
||||
// Handle version specified tool name
|
||||
if i := strings.LastIndex(arg, "@"); i > -1 {
|
||||
name = arg[:i]
|
||||
if len(version) > 0 {
|
||||
return nil, fmt.Errorf("cannot specify --version flag and @ syntax at the same time for %s", name)
|
||||
}
|
||||
version = arg[i+1:]
|
||||
}
|
||||
|
||||
err := toolExists(&arkadeTools, tools, name, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// unset value for the next iteration of versioned tool
|
||||
version = ""
|
||||
}
|
||||
|
||||
return arkadeTools, nil
|
||||
}
|
||||
|
||||
// toolExists checks if user provided tool exists on arkade
|
||||
func toolExists(arkadeTools *[]Tool, tools Tools, name, version string) error {
|
||||
for _, tool := range tools {
|
||||
if name == tool.Name {
|
||||
if len(version) > 0 {
|
||||
tool.Version = version
|
||||
}
|
||||
*arkadeTools = append(*arkadeTools, tool)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("tool %s not found", name)
|
||||
}
|
||||
|
||||
// PostInstallationMsg generates installation message after tool has been downloaded
|
||||
func PostInstallationMsg(dlMode int, localToolsStore []ToolLocal) ([]byte, error) {
|
||||
|
||||
t := template.New("Installation Instructions")
|
||||
|
||||
if dlMode == DownloadTempDir {
|
||||
t.Parse(`Run the following to copy to install the tool:
|
||||
|
||||
chmod +x {{range .}}{{.Path}} {{end}}
|
||||
{{- range . }}
|
||||
sudo install -m 755 {{.Path}} /usr/local/bin/{{.Name}}
|
||||
{{- end}}`)
|
||||
|
||||
} else {
|
||||
t.Parse(`# Add arkade binary directory to your PATH variable
|
||||
export PATH=$PATH:$HOME/.arkade/bin/
|
||||
|
||||
# Test the binary:
|
||||
{{- range . }}
|
||||
{{.Path}}
|
||||
{{- end }}
|
||||
|
||||
# Or install with:
|
||||
{{- range . }}
|
||||
sudo mv {{.Path}} /usr/local/bin/
|
||||
|
||||
{{- end}}`)
|
||||
}
|
||||
|
||||
var tpl bytes.Buffer
|
||||
|
||||
err := t.Execute(&tpl, localToolsStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tpl.Bytes(), err
|
||||
}
|
||||
|
||||
// ValidateOS returns whether a given operating system is supported
|
||||
func ValidateOS(name string) error {
|
||||
for _, os := range supportedOS {
|
||||
if strings.HasPrefix(strings.ToLower(name), os) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("operating system %q is not supported. Available prefixes: %s.",
|
||||
name, strings.Join(supportedOS[:], ", "))
|
||||
}
|
||||
|
||||
// ValidateArch returns whether a given cpu architecture is supported
|
||||
func ValidateArch(name string) error {
|
||||
for _, arch := range supportedArchitectures {
|
||||
if arch == strings.ToLower(name) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("cpu architecture %q is not supported. Available: %s.",
|
||||
name, strings.Join(supportedArchitectures[:], ", "))
|
||||
}
|
||||
41
vendor/github.com/alexellis/arkade/pkg/get/table.go
generated
vendored
Normal file
41
vendor/github.com/alexellis/arkade/pkg/get/table.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package get
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
type TableFormat string
|
||||
|
||||
const (
|
||||
TableStyle TableFormat = "table"
|
||||
MarkdownStyle TableFormat = "markdown"
|
||||
ListStyle TableFormat = "list"
|
||||
)
|
||||
|
||||
// CreateToolTable creates table to show the avaiable CLI tools
|
||||
func CreateToolsTable(tools Tools, format TableFormat) {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Tool", "Description"})
|
||||
table.SetCaption(true,
|
||||
fmt.Sprintf("There are %d tools, use `arkade get NAME` to download one.", len(tools)))
|
||||
if format == MarkdownStyle {
|
||||
table.SetCaption(true)
|
||||
table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
|
||||
table.SetCenterSeparator("|")
|
||||
table.SetAutoWrapText(false)
|
||||
} else {
|
||||
table.SetRowLine(true)
|
||||
table.SetColWidth(60)
|
||||
table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold}, tablewriter.Colors{})
|
||||
table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgGreenColor}, tablewriter.Colors{})
|
||||
}
|
||||
|
||||
for _, t := range tools {
|
||||
table.Append([]string{t.Name, t.Description})
|
||||
}
|
||||
|
||||
table.Render()
|
||||
}
|
||||
2860
vendor/github.com/alexellis/arkade/pkg/get/tools.go
generated
vendored
Normal file
2860
vendor/github.com/alexellis/arkade/pkg/get/tools.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
vendor/github.com/cheggaaa/pb/v3/LICENSE
generated
vendored
Normal file
12
vendor/github.com/cheggaaa/pb/v3/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (c) 2012-2015, Sergey Cherepanov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
330
vendor/github.com/cheggaaa/pb/v3/element.go
generated
vendored
Normal file
330
vendor/github.com/cheggaaa/pb/v3/element.go
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
adElPlaceholder = "%_ad_el_%"
|
||||
adElPlaceholderLen = len(adElPlaceholder)
|
||||
)
|
||||
|
||||
var (
|
||||
defaultBarEls = [5]string{"[", "-", ">", "_", "]"}
|
||||
)
|
||||
|
||||
// Element is an interface for bar elements
|
||||
type Element interface {
|
||||
ProgressElement(state *State, args ...string) string
|
||||
}
|
||||
|
||||
// ElementFunc type implements Element interface and created for simplify elements
|
||||
type ElementFunc func(state *State, args ...string) string
|
||||
|
||||
// ProgressElement just call self func
|
||||
func (e ElementFunc) ProgressElement(state *State, args ...string) string {
|
||||
return e(state, args...)
|
||||
}
|
||||
|
||||
var elementsM sync.Mutex
|
||||
|
||||
var elements = map[string]Element{
|
||||
"percent": ElementPercent,
|
||||
"counters": ElementCounters,
|
||||
"bar": adaptiveWrap(ElementBar),
|
||||
"speed": ElementSpeed,
|
||||
"rtime": ElementRemainingTime,
|
||||
"etime": ElementElapsedTime,
|
||||
"string": ElementString,
|
||||
"cycle": ElementCycle,
|
||||
}
|
||||
|
||||
// RegisterElement give you a chance to use custom elements
|
||||
func RegisterElement(name string, el Element, adaptive bool) {
|
||||
if adaptive {
|
||||
el = adaptiveWrap(el)
|
||||
}
|
||||
elementsM.Lock()
|
||||
elements[name] = el
|
||||
elementsM.Unlock()
|
||||
}
|
||||
|
||||
type argsHelper []string
|
||||
|
||||
func (args argsHelper) getOr(n int, value string) string {
|
||||
if len(args) > n {
|
||||
return args[n]
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (args argsHelper) getNotEmptyOr(n int, value string) (v string) {
|
||||
if v = args.getOr(n, value); v == "" {
|
||||
return value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func adaptiveWrap(el Element) Element {
|
||||
return ElementFunc(func(state *State, args ...string) string {
|
||||
state.recalc = append(state.recalc, ElementFunc(func(s *State, _ ...string) (result string) {
|
||||
s.adaptive = true
|
||||
result = el.ProgressElement(s, args...)
|
||||
s.adaptive = false
|
||||
return
|
||||
}))
|
||||
return adElPlaceholder
|
||||
})
|
||||
}
|
||||
|
||||
// ElementPercent shows current percent of progress.
|
||||
// Optionally can take one or two string arguments.
|
||||
// First string will be used as value for format float64, default is "%.02f%%".
|
||||
// Second string will be used when percent can't be calculated, default is "?%"
|
||||
// In template use as follows: {{percent .}} or {{percent . "%.03f%%"}} or {{percent . "%.03f%%" "?"}}
|
||||
var ElementPercent ElementFunc = func(state *State, args ...string) string {
|
||||
argsh := argsHelper(args)
|
||||
if state.Total() > 0 {
|
||||
return fmt.Sprintf(
|
||||
argsh.getNotEmptyOr(0, "%.02f%%"),
|
||||
float64(state.Value())/(float64(state.Total())/float64(100)),
|
||||
)
|
||||
}
|
||||
return argsh.getOr(1, "?%")
|
||||
}
|
||||
|
||||
// ElementCounters shows current and total values.
|
||||
// Optionally can take one or two string arguments.
|
||||
// First string will be used as format value when Total is present (>0). Default is "%s / %s"
|
||||
// Second string will be used when total <= 0. Default is "%[1]s"
|
||||
// In template use as follows: {{counters .}} or {{counters . "%s/%s"}} or {{counters . "%s/%s" "%s/?"}}
|
||||
var ElementCounters ElementFunc = func(state *State, args ...string) string {
|
||||
var f string
|
||||
if state.Total() > 0 {
|
||||
f = argsHelper(args).getNotEmptyOr(0, "%s / %s")
|
||||
} else {
|
||||
f = argsHelper(args).getNotEmptyOr(1, "%[1]s")
|
||||
}
|
||||
return fmt.Sprintf(f, state.Format(state.Value()), state.Format(state.Total()))
|
||||
}
|
||||
|
||||
type elementKey int
|
||||
|
||||
const (
|
||||
barObj elementKey = iota
|
||||
speedObj
|
||||
cycleObj
|
||||
)
|
||||
|
||||
type bar struct {
|
||||
eb [5][]byte // elements in bytes
|
||||
cc [5]int // cell counts
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
func (p *bar) write(state *State, eln, width int) int {
|
||||
repeat := width / p.cc[eln]
|
||||
remainder := width % p.cc[eln]
|
||||
for i := 0; i < repeat; i++ {
|
||||
p.buf.Write(p.eb[eln])
|
||||
}
|
||||
if remainder > 0 {
|
||||
StripStringToBuffer(string(p.eb[eln]), remainder, p.buf)
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
func getProgressObj(state *State, args ...string) (p *bar) {
|
||||
var ok bool
|
||||
if p, ok = state.Get(barObj).(*bar); !ok {
|
||||
p = &bar{
|
||||
buf: bytes.NewBuffer(nil),
|
||||
}
|
||||
state.Set(barObj, p)
|
||||
}
|
||||
argsH := argsHelper(args)
|
||||
for i := range p.eb {
|
||||
arg := argsH.getNotEmptyOr(i, defaultBarEls[i])
|
||||
if string(p.eb[i]) != arg {
|
||||
p.cc[i] = CellCount(arg)
|
||||
p.eb[i] = []byte(arg)
|
||||
if p.cc[i] == 0 {
|
||||
p.cc[i] = 1
|
||||
p.eb[i] = []byte(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ElementBar make progress bar view [-->__]
|
||||
// Optionally can take up to 5 string arguments. Defaults is "[", "-", ">", "_", "]"
|
||||
// In template use as follows: {{bar . }} or {{bar . "<" "oOo" "|" "~" ">"}}
|
||||
// Color args: {{bar . (red "[") (green "-") ...
|
||||
var ElementBar ElementFunc = func(state *State, args ...string) string {
|
||||
// init
|
||||
var p = getProgressObj(state, args...)
|
||||
|
||||
total, value := state.Total(), state.Value()
|
||||
if total < 0 {
|
||||
total = -total
|
||||
}
|
||||
if value < 0 {
|
||||
value = -value
|
||||
}
|
||||
|
||||
// check for overflow
|
||||
if total != 0 && value > total {
|
||||
total = value
|
||||
}
|
||||
|
||||
p.buf.Reset()
|
||||
|
||||
var widthLeft = state.AdaptiveElWidth()
|
||||
if widthLeft <= 0 || !state.IsAdaptiveWidth() {
|
||||
widthLeft = 30
|
||||
}
|
||||
|
||||
// write left border
|
||||
if p.cc[0] < widthLeft {
|
||||
widthLeft -= p.write(state, 0, p.cc[0])
|
||||
} else {
|
||||
p.write(state, 0, widthLeft)
|
||||
return p.buf.String()
|
||||
}
|
||||
|
||||
// check right border size
|
||||
if p.cc[4] < widthLeft {
|
||||
// write later
|
||||
widthLeft -= p.cc[4]
|
||||
} else {
|
||||
p.write(state, 4, widthLeft)
|
||||
return p.buf.String()
|
||||
}
|
||||
|
||||
var curCount int
|
||||
|
||||
if total > 0 {
|
||||
// calculate count of currenct space
|
||||
curCount = int(math.Ceil((float64(value) / float64(total)) * float64(widthLeft)))
|
||||
}
|
||||
|
||||
// write bar
|
||||
if total == value && state.IsFinished() {
|
||||
widthLeft -= p.write(state, 1, curCount)
|
||||
} else if toWrite := curCount - p.cc[2]; toWrite > 0 {
|
||||
widthLeft -= p.write(state, 1, toWrite)
|
||||
widthLeft -= p.write(state, 2, p.cc[2])
|
||||
} else if curCount > 0 {
|
||||
widthLeft -= p.write(state, 2, curCount)
|
||||
}
|
||||
if widthLeft > 0 {
|
||||
widthLeft -= p.write(state, 3, widthLeft)
|
||||
}
|
||||
// write right border
|
||||
p.write(state, 4, p.cc[4])
|
||||
// cut result and return string
|
||||
return p.buf.String()
|
||||
}
|
||||
|
||||
func elapsedTime(state *State) string {
|
||||
elapsed := state.Time().Sub(state.StartTime())
|
||||
var precision time.Duration
|
||||
var ok bool
|
||||
if precision, ok = state.Get(TimeRound).(time.Duration); !ok {
|
||||
// default behavior: round to nearest .1s when elapsed < 10s
|
||||
//
|
||||
// we compare with 9.95s as opposed to 10s to avoid an annoying
|
||||
// interaction with the fixed precision display code below,
|
||||
// where 9.9s would be rounded to 10s but printed as 10.0s, and
|
||||
// then 10.0s would be rounded to 10s and printed as 10s
|
||||
if elapsed < 9950*time.Millisecond {
|
||||
precision = 100 * time.Millisecond
|
||||
} else {
|
||||
precision = time.Second
|
||||
}
|
||||
}
|
||||
rounded := elapsed.Round(precision)
|
||||
if precision < time.Second && rounded >= time.Second {
|
||||
// special handling to ensure string is shown with the given
|
||||
// precision, with trailing zeros after the decimal point if
|
||||
// necessary
|
||||
reference := (2*time.Second - time.Nanosecond).Truncate(precision).String()
|
||||
// reference looks like "1.9[...]9s", telling us how many
|
||||
// decimal digits we need
|
||||
neededDecimals := len(reference) - 3
|
||||
s := rounded.String()
|
||||
dotIndex := strings.LastIndex(s, ".")
|
||||
if dotIndex != -1 {
|
||||
// s has the form "[stuff].[decimals]s"
|
||||
decimals := len(s) - dotIndex - 2
|
||||
extraZeros := neededDecimals - decimals
|
||||
return fmt.Sprintf("%s%ss", s[:len(s)-1], strings.Repeat("0", extraZeros))
|
||||
} else {
|
||||
// s has the form "[stuff]s"
|
||||
return fmt.Sprintf("%s.%ss", s[:len(s)-1], strings.Repeat("0", neededDecimals))
|
||||
}
|
||||
} else {
|
||||
return rounded.String()
|
||||
}
|
||||
}
|
||||
|
||||
// ElementRemainingTime calculates remaining time based on speed (EWMA)
|
||||
// Optionally can take one or two string arguments.
|
||||
// First string will be used as value for format time duration string, default is "%s".
|
||||
// Second string will be used when bar finished and value indicates elapsed time, default is "%s"
|
||||
// Third string will be used when value not available, default is "?"
|
||||
// In template use as follows: {{rtime .}} or {{rtime . "%s remain"}} or {{rtime . "%s remain" "%s total" "???"}}
|
||||
var ElementRemainingTime ElementFunc = func(state *State, args ...string) string {
|
||||
if state.IsFinished() {
|
||||
return fmt.Sprintf(argsHelper(args).getOr(1, "%s"), elapsedTime(state))
|
||||
}
|
||||
sp := getSpeedObj(state).value(state)
|
||||
if sp > 0 {
|
||||
remain := float64(state.Total() - state.Value())
|
||||
remainDur := time.Duration(remain/sp) * time.Second
|
||||
return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), remainDur)
|
||||
}
|
||||
return argsHelper(args).getOr(2, "?")
|
||||
}
|
||||
|
||||
// ElementElapsedTime shows elapsed time
|
||||
// Optionally can take one argument - it's format for time string.
|
||||
// In template use as follows: {{etime .}} or {{etime . "%s elapsed"}}
|
||||
var ElementElapsedTime ElementFunc = func(state *State, args ...string) string {
|
||||
return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), elapsedTime(state))
|
||||
}
|
||||
|
||||
// ElementString get value from bar by given key and print them
|
||||
// bar.Set("myKey", "string to print")
|
||||
// In template use as follows: {{string . "myKey"}}
|
||||
var ElementString ElementFunc = func(state *State, args ...string) string {
|
||||
if len(args) == 0 {
|
||||
return ""
|
||||
}
|
||||
v := state.Get(args[0])
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(v)
|
||||
}
|
||||
|
||||
// ElementCycle return next argument for every call
|
||||
// In template use as follows: {{cycle . "1" "2" "3"}}
|
||||
// Or mix width other elements: {{ bar . "" "" (cycle . "↖" "↗" "↘" "↙" )}}
|
||||
var ElementCycle ElementFunc = func(state *State, args ...string) string {
|
||||
if len(args) == 0 {
|
||||
return ""
|
||||
}
|
||||
n, _ := state.Get(cycleObj).(int)
|
||||
if n >= len(args) {
|
||||
n = 0
|
||||
}
|
||||
state.Set(cycleObj, n+1)
|
||||
return args[n]
|
||||
}
|
||||
49
vendor/github.com/cheggaaa/pb/v3/io.go
generated
vendored
Normal file
49
vendor/github.com/cheggaaa/pb/v3/io.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Reader it's a wrapper for given reader, but with progress handle
|
||||
type Reader struct {
|
||||
io.Reader
|
||||
bar *ProgressBar
|
||||
}
|
||||
|
||||
// Read reads bytes from wrapped reader and add amount of bytes to progress bar
|
||||
func (r *Reader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.Reader.Read(p)
|
||||
r.bar.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Close the wrapped reader when it implements io.Closer
|
||||
func (r *Reader) Close() (err error) {
|
||||
r.bar.Finish()
|
||||
if closer, ok := r.Reader.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Writer it's a wrapper for given writer, but with progress handle
|
||||
type Writer struct {
|
||||
io.Writer
|
||||
bar *ProgressBar
|
||||
}
|
||||
|
||||
// Write writes bytes to wrapped writer and add amount of bytes to progress bar
|
||||
func (r *Writer) Write(p []byte) (n int, err error) {
|
||||
n, err = r.Writer.Write(p)
|
||||
r.bar.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Close the wrapped reader when it implements io.Closer
|
||||
func (r *Writer) Close() (err error) {
|
||||
r.bar.Finish()
|
||||
if closer, ok := r.Writer.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
595
vendor/github.com/cheggaaa/pb/v3/pb.go
generated
vendored
Normal file
595
vendor/github.com/cheggaaa/pb/v3/pb.go
generated
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
|
||||
"github.com/cheggaaa/pb/v3/termutil"
|
||||
)
|
||||
|
||||
// Version of ProgressBar library
|
||||
const Version = "3.0.8"
|
||||
|
||||
type key int
|
||||
|
||||
const (
|
||||
// Bytes means we're working with byte sizes. Numbers will print as Kb, Mb, etc
|
||||
// bar.Set(pb.Bytes, true)
|
||||
Bytes key = 1 << iota
|
||||
|
||||
// Use SI bytes prefix names (kB, MB, etc) instead of IEC prefix names (KiB, MiB, etc)
|
||||
SIBytesPrefix
|
||||
|
||||
// Terminal means we're will print to terminal and can use ascii sequences
|
||||
// Also we're will try to use terminal width
|
||||
Terminal
|
||||
|
||||
// Static means progress bar will not update automaticly
|
||||
Static
|
||||
|
||||
// ReturnSymbol - by default in terminal mode it's '\r'
|
||||
ReturnSymbol
|
||||
|
||||
// Color by default is true when output is tty, but you can set to false for disabling colors
|
||||
Color
|
||||
|
||||
// Hide the progress bar when finished, rather than leaving it up. By default it's false.
|
||||
CleanOnFinish
|
||||
|
||||
// Round elapsed time to this precision. Defaults to time.Second.
|
||||
TimeRound
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBarWidth = 100
|
||||
defaultRefreshRate = time.Millisecond * 200
|
||||
)
|
||||
|
||||
// New creates new ProgressBar object
|
||||
func New(total int) *ProgressBar {
|
||||
return New64(int64(total))
|
||||
}
|
||||
|
||||
// New64 creates new ProgressBar object using int64 as total
|
||||
func New64(total int64) *ProgressBar {
|
||||
pb := new(ProgressBar)
|
||||
return pb.SetTotal(total)
|
||||
}
|
||||
|
||||
// StartNew starts new ProgressBar with Default template
|
||||
func StartNew(total int) *ProgressBar {
|
||||
return New(total).Start()
|
||||
}
|
||||
|
||||
// Start64 starts new ProgressBar with Default template. Using int64 as total.
|
||||
func Start64(total int64) *ProgressBar {
|
||||
return New64(total).Start()
|
||||
}
|
||||
|
||||
var (
|
||||
terminalWidth = termutil.TerminalWidth
|
||||
isTerminal = isatty.IsTerminal
|
||||
isCygwinTerminal = isatty.IsCygwinTerminal
|
||||
)
|
||||
|
||||
// ProgressBar is the main object of bar
|
||||
type ProgressBar struct {
|
||||
current, total int64
|
||||
width int
|
||||
maxWidth int
|
||||
mu sync.RWMutex
|
||||
rm sync.Mutex
|
||||
vars map[interface{}]interface{}
|
||||
elements map[string]Element
|
||||
output io.Writer
|
||||
coutput io.Writer
|
||||
nocoutput io.Writer
|
||||
startTime time.Time
|
||||
refreshRate time.Duration
|
||||
tmpl *template.Template
|
||||
state *State
|
||||
buf *bytes.Buffer
|
||||
ticker *time.Ticker
|
||||
finish chan struct{}
|
||||
finished bool
|
||||
configured bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) configure() {
|
||||
if pb.configured {
|
||||
return
|
||||
}
|
||||
pb.configured = true
|
||||
|
||||
if pb.vars == nil {
|
||||
pb.vars = make(map[interface{}]interface{})
|
||||
}
|
||||
if pb.output == nil {
|
||||
pb.output = os.Stderr
|
||||
}
|
||||
|
||||
if pb.tmpl == nil {
|
||||
pb.tmpl, pb.err = getTemplate(string(Default))
|
||||
if pb.err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if pb.vars[Terminal] == nil {
|
||||
if f, ok := pb.output.(*os.File); ok {
|
||||
if isTerminal(f.Fd()) || isCygwinTerminal(f.Fd()) {
|
||||
pb.vars[Terminal] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if pb.vars[ReturnSymbol] == nil {
|
||||
if tm, ok := pb.vars[Terminal].(bool); ok && tm {
|
||||
pb.vars[ReturnSymbol] = "\r"
|
||||
}
|
||||
}
|
||||
if pb.vars[Color] == nil {
|
||||
if tm, ok := pb.vars[Terminal].(bool); ok && tm {
|
||||
pb.vars[Color] = true
|
||||
}
|
||||
}
|
||||
if pb.refreshRate == 0 {
|
||||
pb.refreshRate = defaultRefreshRate
|
||||
}
|
||||
if pb.vars[CleanOnFinish] == nil {
|
||||
pb.vars[CleanOnFinish] = false
|
||||
}
|
||||
if f, ok := pb.output.(*os.File); ok {
|
||||
pb.coutput = colorable.NewColorable(f)
|
||||
} else {
|
||||
pb.coutput = pb.output
|
||||
}
|
||||
pb.nocoutput = colorable.NewNonColorable(pb.output)
|
||||
}
|
||||
|
||||
// Start starts the bar
|
||||
func (pb *ProgressBar) Start() *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
defer pb.mu.Unlock()
|
||||
if pb.finish != nil {
|
||||
return pb
|
||||
}
|
||||
pb.configure()
|
||||
pb.finished = false
|
||||
pb.state = nil
|
||||
pb.startTime = time.Now()
|
||||
if st, ok := pb.vars[Static].(bool); ok && st {
|
||||
return pb
|
||||
}
|
||||
pb.finish = make(chan struct{})
|
||||
pb.ticker = time.NewTicker(pb.refreshRate)
|
||||
go pb.writer(pb.finish)
|
||||
return pb
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) writer(finish chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case <-pb.ticker.C:
|
||||
pb.write(false)
|
||||
case <-finish:
|
||||
pb.ticker.Stop()
|
||||
pb.write(true)
|
||||
finish <- struct{}{}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write performs write to the output
|
||||
func (pb *ProgressBar) Write() *ProgressBar {
|
||||
pb.mu.RLock()
|
||||
finished := pb.finished
|
||||
pb.mu.RUnlock()
|
||||
pb.write(finished)
|
||||
return pb
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) write(finish bool) {
|
||||
result, width := pb.render()
|
||||
if pb.Err() != nil {
|
||||
return
|
||||
}
|
||||
if pb.GetBool(Terminal) {
|
||||
if r := (width - CellCount(result)); r > 0 {
|
||||
result += strings.Repeat(" ", r)
|
||||
}
|
||||
}
|
||||
if ret, ok := pb.Get(ReturnSymbol).(string); ok {
|
||||
result = ret + result
|
||||
if finish && ret == "\r" {
|
||||
if pb.GetBool(CleanOnFinish) {
|
||||
// "Wipe out" progress bar by overwriting one line with blanks
|
||||
result = "\r" + color.New(color.Reset).Sprintf(strings.Repeat(" ", width)) + "\r"
|
||||
} else {
|
||||
result += "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
if pb.GetBool(Color) {
|
||||
pb.coutput.Write([]byte(result))
|
||||
} else {
|
||||
pb.nocoutput.Write([]byte(result))
|
||||
}
|
||||
}
|
||||
|
||||
// Total return current total bar value
|
||||
func (pb *ProgressBar) Total() int64 {
|
||||
return atomic.LoadInt64(&pb.total)
|
||||
}
|
||||
|
||||
// SetTotal sets the total bar value
|
||||
func (pb *ProgressBar) SetTotal(value int64) *ProgressBar {
|
||||
atomic.StoreInt64(&pb.total, value)
|
||||
return pb
|
||||
}
|
||||
|
||||
// AddTotal adds to the total bar value
|
||||
func (pb *ProgressBar) AddTotal(value int64) *ProgressBar {
|
||||
atomic.AddInt64(&pb.total, value)
|
||||
return pb
|
||||
}
|
||||
|
||||
// SetCurrent sets the current bar value
|
||||
func (pb *ProgressBar) SetCurrent(value int64) *ProgressBar {
|
||||
atomic.StoreInt64(&pb.current, value)
|
||||
return pb
|
||||
}
|
||||
|
||||
// Current return current bar value
|
||||
func (pb *ProgressBar) Current() int64 {
|
||||
return atomic.LoadInt64(&pb.current)
|
||||
}
|
||||
|
||||
// Add adding given int64 value to bar value
|
||||
func (pb *ProgressBar) Add64(value int64) *ProgressBar {
|
||||
atomic.AddInt64(&pb.current, value)
|
||||
return pb
|
||||
}
|
||||
|
||||
// Add adding given int value to bar value
|
||||
func (pb *ProgressBar) Add(value int) *ProgressBar {
|
||||
return pb.Add64(int64(value))
|
||||
}
|
||||
|
||||
// Increment atomically increments the progress
|
||||
func (pb *ProgressBar) Increment() *ProgressBar {
|
||||
return pb.Add64(1)
|
||||
}
|
||||
|
||||
// Set sets any value by any key
|
||||
func (pb *ProgressBar) Set(key, value interface{}) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
defer pb.mu.Unlock()
|
||||
if pb.vars == nil {
|
||||
pb.vars = make(map[interface{}]interface{})
|
||||
}
|
||||
pb.vars[key] = value
|
||||
return pb
|
||||
}
|
||||
|
||||
// Get return value by key
|
||||
func (pb *ProgressBar) Get(key interface{}) interface{} {
|
||||
pb.mu.RLock()
|
||||
defer pb.mu.RUnlock()
|
||||
if pb.vars == nil {
|
||||
return nil
|
||||
}
|
||||
return pb.vars[key]
|
||||
}
|
||||
|
||||
// GetBool return value by key and try to convert there to boolean
|
||||
// If value doesn't set or not boolean - return false
|
||||
func (pb *ProgressBar) GetBool(key interface{}) bool {
|
||||
if v, ok := pb.Get(key).(bool); ok {
|
||||
return v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetWidth sets the bar width
|
||||
// When given value <= 0 would be using the terminal width (if possible) or default value.
|
||||
func (pb *ProgressBar) SetWidth(width int) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
pb.width = width
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// SetMaxWidth sets the bar maximum width
|
||||
// When given value <= 0 would be using the terminal width (if possible) or default value.
|
||||
func (pb *ProgressBar) SetMaxWidth(maxWidth int) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
pb.maxWidth = maxWidth
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// Width return the bar width
|
||||
// It's current terminal width or settled over 'SetWidth' value.
|
||||
func (pb *ProgressBar) Width() (width int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
width = defaultBarWidth
|
||||
}
|
||||
}()
|
||||
pb.mu.RLock()
|
||||
width = pb.width
|
||||
maxWidth := pb.maxWidth
|
||||
pb.mu.RUnlock()
|
||||
if width <= 0 {
|
||||
var err error
|
||||
if width, err = terminalWidth(); err != nil {
|
||||
return defaultBarWidth
|
||||
}
|
||||
}
|
||||
if maxWidth > 0 && width > maxWidth {
|
||||
width = maxWidth
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) SetRefreshRate(dur time.Duration) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
if dur > 0 {
|
||||
pb.refreshRate = dur
|
||||
}
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// SetWriter sets the io.Writer. Bar will write in this writer
|
||||
// By default this is os.Stderr
|
||||
func (pb *ProgressBar) SetWriter(w io.Writer) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
pb.output = w
|
||||
pb.configured = false
|
||||
pb.configure()
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// StartTime return the time when bar started
|
||||
func (pb *ProgressBar) StartTime() time.Time {
|
||||
pb.mu.RLock()
|
||||
defer pb.mu.RUnlock()
|
||||
return pb.startTime
|
||||
}
|
||||
|
||||
// Format convert int64 to string according to the current settings
|
||||
func (pb *ProgressBar) Format(v int64) string {
|
||||
if pb.GetBool(Bytes) {
|
||||
return formatBytes(v, pb.GetBool(SIBytesPrefix))
|
||||
}
|
||||
return strconv.FormatInt(v, 10)
|
||||
}
|
||||
|
||||
// Finish stops the bar
|
||||
func (pb *ProgressBar) Finish() *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
if pb.finished {
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
finishChan := pb.finish
|
||||
pb.finished = true
|
||||
pb.mu.Unlock()
|
||||
if finishChan != nil {
|
||||
finishChan <- struct{}{}
|
||||
<-finishChan
|
||||
pb.mu.Lock()
|
||||
pb.finish = nil
|
||||
pb.mu.Unlock()
|
||||
}
|
||||
return pb
|
||||
}
|
||||
|
||||
// IsStarted indicates progress bar state
|
||||
func (pb *ProgressBar) IsStarted() bool {
|
||||
pb.mu.RLock()
|
||||
defer pb.mu.RUnlock()
|
||||
return pb.finish != nil
|
||||
}
|
||||
|
||||
// IsFinished indicates progress bar is finished
|
||||
func (pb *ProgressBar) IsFinished() bool {
|
||||
pb.mu.RLock()
|
||||
defer pb.mu.RUnlock()
|
||||
return pb.finished
|
||||
}
|
||||
|
||||
// SetTemplateString sets ProgressBar tempate string and parse it
|
||||
func (pb *ProgressBar) SetTemplateString(tmpl string) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
defer pb.mu.Unlock()
|
||||
pb.tmpl, pb.err = getTemplate(tmpl)
|
||||
return pb
|
||||
}
|
||||
|
||||
// SetTemplateString sets ProgressBarTempate and parse it
|
||||
func (pb *ProgressBar) SetTemplate(tmpl ProgressBarTemplate) *ProgressBar {
|
||||
return pb.SetTemplateString(string(tmpl))
|
||||
}
|
||||
|
||||
// NewProxyReader creates a wrapper for given reader, but with progress handle
|
||||
// Takes io.Reader or io.ReadCloser
|
||||
// Also, it automatically switches progress bar to handle units as bytes
|
||||
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
|
||||
pb.Set(Bytes, true)
|
||||
return &Reader{r, pb}
|
||||
}
|
||||
|
||||
// NewProxyWriter creates a wrapper for given writer, but with progress handle
|
||||
// Takes io.Writer or io.WriteCloser
|
||||
// Also, it automatically switches progress bar to handle units as bytes
|
||||
func (pb *ProgressBar) NewProxyWriter(r io.Writer) *Writer {
|
||||
pb.Set(Bytes, true)
|
||||
return &Writer{r, pb}
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) render() (result string, width int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
pb.SetErr(fmt.Errorf("render panic: %v", r))
|
||||
}
|
||||
}()
|
||||
pb.rm.Lock()
|
||||
defer pb.rm.Unlock()
|
||||
pb.mu.Lock()
|
||||
pb.configure()
|
||||
if pb.state == nil {
|
||||
pb.state = &State{ProgressBar: pb}
|
||||
pb.buf = bytes.NewBuffer(nil)
|
||||
}
|
||||
if pb.startTime.IsZero() {
|
||||
pb.startTime = time.Now()
|
||||
}
|
||||
pb.state.id++
|
||||
pb.state.finished = pb.finished
|
||||
pb.state.time = time.Now()
|
||||
pb.mu.Unlock()
|
||||
|
||||
pb.state.width = pb.Width()
|
||||
width = pb.state.width
|
||||
pb.state.total = pb.Total()
|
||||
pb.state.current = pb.Current()
|
||||
pb.buf.Reset()
|
||||
|
||||
if e := pb.tmpl.Execute(pb.buf, pb.state); e != nil {
|
||||
pb.SetErr(e)
|
||||
return "", 0
|
||||
}
|
||||
|
||||
result = pb.buf.String()
|
||||
|
||||
aec := len(pb.state.recalc)
|
||||
if aec == 0 {
|
||||
// no adaptive elements
|
||||
return
|
||||
}
|
||||
|
||||
staticWidth := CellCount(result) - (aec * adElPlaceholderLen)
|
||||
|
||||
if pb.state.Width()-staticWidth <= 0 {
|
||||
result = strings.Replace(result, adElPlaceholder, "", -1)
|
||||
result = StripString(result, pb.state.Width())
|
||||
} else {
|
||||
pb.state.adaptiveElWidth = (width - staticWidth) / aec
|
||||
for _, el := range pb.state.recalc {
|
||||
result = strings.Replace(result, adElPlaceholder, el.ProgressElement(pb.state), 1)
|
||||
}
|
||||
}
|
||||
pb.state.recalc = pb.state.recalc[:0]
|
||||
return
|
||||
}
|
||||
|
||||
// SetErr sets error to the ProgressBar
|
||||
// Error will be available over Err()
|
||||
func (pb *ProgressBar) SetErr(err error) *ProgressBar {
|
||||
pb.mu.Lock()
|
||||
pb.err = err
|
||||
pb.mu.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// Err return possible error
|
||||
// When all ok - will be nil
|
||||
// May contain template.Execute errors
|
||||
func (pb *ProgressBar) Err() error {
|
||||
pb.mu.RLock()
|
||||
defer pb.mu.RUnlock()
|
||||
return pb.err
|
||||
}
|
||||
|
||||
// String return currrent string representation of ProgressBar
|
||||
func (pb *ProgressBar) String() string {
|
||||
res, _ := pb.render()
|
||||
return res
|
||||
}
|
||||
|
||||
// ProgressElement implements Element interface
|
||||
func (pb *ProgressBar) ProgressElement(s *State, args ...string) string {
|
||||
if s.IsAdaptiveWidth() {
|
||||
pb.SetWidth(s.AdaptiveElWidth())
|
||||
}
|
||||
return pb.String()
|
||||
}
|
||||
|
||||
// State represents the current state of bar
|
||||
// Need for bar elements
|
||||
type State struct {
|
||||
*ProgressBar
|
||||
|
||||
id uint64
|
||||
total, current int64
|
||||
width, adaptiveElWidth int
|
||||
finished, adaptive bool
|
||||
time time.Time
|
||||
|
||||
recalc []Element
|
||||
}
|
||||
|
||||
// Id it's the current state identifier
|
||||
// - incremental
|
||||
// - starts with 1
|
||||
// - resets after finish/start
|
||||
func (s *State) Id() uint64 {
|
||||
return s.id
|
||||
}
|
||||
|
||||
// Total it's bar int64 total
|
||||
func (s *State) Total() int64 {
|
||||
return s.total
|
||||
}
|
||||
|
||||
// Value it's current value
|
||||
func (s *State) Value() int64 {
|
||||
return s.current
|
||||
}
|
||||
|
||||
// Width of bar
|
||||
func (s *State) Width() int {
|
||||
return s.width
|
||||
}
|
||||
|
||||
// AdaptiveElWidth - adaptive elements must return string with given cell count (when AdaptiveElWidth > 0)
|
||||
func (s *State) AdaptiveElWidth() int {
|
||||
return s.adaptiveElWidth
|
||||
}
|
||||
|
||||
// IsAdaptiveWidth returns true when element must be shown as adaptive
|
||||
func (s *State) IsAdaptiveWidth() bool {
|
||||
return s.adaptive
|
||||
}
|
||||
|
||||
// IsFinished return true when bar is finished
|
||||
func (s *State) IsFinished() bool {
|
||||
return s.finished
|
||||
}
|
||||
|
||||
// IsFirst return true only in first render
|
||||
func (s *State) IsFirst() bool {
|
||||
return s.id == 1
|
||||
}
|
||||
|
||||
// Time when state was created
|
||||
func (s *State) Time() time.Time {
|
||||
return s.time
|
||||
}
|
||||
105
vendor/github.com/cheggaaa/pb/v3/pool.go
generated
vendored
Normal file
105
vendor/github.com/cheggaaa/pb/v3/pool.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly windows plan9 aix
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cheggaaa/pb/v3/termutil"
|
||||
)
|
||||
|
||||
// Create and start new pool with given bars
|
||||
// You need call pool.Stop() after work
|
||||
func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
|
||||
pool = new(Pool)
|
||||
if err = pool.Start(); err != nil {
|
||||
return
|
||||
}
|
||||
pool.Add(pbs...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewPool initialises a pool with progress bars, but
|
||||
// doesn't start it. You need to call Start manually
|
||||
func NewPool(pbs ...*ProgressBar) (pool *Pool) {
|
||||
pool = new(Pool)
|
||||
pool.Add(pbs...)
|
||||
return
|
||||
}
|
||||
|
||||
type Pool struct {
|
||||
Output io.Writer
|
||||
RefreshRate time.Duration
|
||||
bars []*ProgressBar
|
||||
lastBarsCount int
|
||||
shutdownCh chan struct{}
|
||||
workerCh chan struct{}
|
||||
m sync.Mutex
|
||||
finishOnce sync.Once
|
||||
}
|
||||
|
||||
// Add progress bars.
|
||||
func (p *Pool) Add(pbs ...*ProgressBar) {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
for _, bar := range pbs {
|
||||
bar.Set(Static, true)
|
||||
bar.Start()
|
||||
p.bars = append(p.bars, bar)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pool) Start() (err error) {
|
||||
p.RefreshRate = defaultRefreshRate
|
||||
p.shutdownCh, err = termutil.RawModeOn()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p.workerCh = make(chan struct{})
|
||||
go p.writer()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Pool) writer() {
|
||||
var first = true
|
||||
defer func() {
|
||||
if first == false {
|
||||
p.print(false)
|
||||
} else {
|
||||
p.print(true)
|
||||
p.print(false)
|
||||
}
|
||||
close(p.workerCh)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(p.RefreshRate):
|
||||
if p.print(first) {
|
||||
p.print(false)
|
||||
return
|
||||
}
|
||||
first = false
|
||||
case <-p.shutdownCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore terminal state and close pool
|
||||
func (p *Pool) Stop() error {
|
||||
p.finishOnce.Do(func() {
|
||||
if p.shutdownCh != nil {
|
||||
close(p.shutdownCh)
|
||||
}
|
||||
})
|
||||
|
||||
// Wait for the worker to complete
|
||||
select {
|
||||
case <-p.workerCh:
|
||||
}
|
||||
|
||||
return termutil.RawModeOff()
|
||||
}
|
||||
46
vendor/github.com/cheggaaa/pb/v3/pool_win.go
generated
vendored
Normal file
46
vendor/github.com/cheggaaa/pb/v3/pool_win.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// +build windows
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/cheggaaa/pb/v3/termutil"
|
||||
)
|
||||
|
||||
func (p *Pool) print(first bool) bool {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
var out string
|
||||
if !first {
|
||||
coords, err := termutil.GetCursorPos()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
coords.Y -= int16(p.lastBarsCount)
|
||||
if coords.Y < 0 {
|
||||
coords.Y = 0
|
||||
}
|
||||
coords.X = 0
|
||||
|
||||
err = termutil.SetCursorPos(coords)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
isFinished := true
|
||||
for _, bar := range p.bars {
|
||||
if !bar.IsFinished() {
|
||||
isFinished = false
|
||||
}
|
||||
out += fmt.Sprintf("\r%s\n", bar.String())
|
||||
}
|
||||
if p.Output != nil {
|
||||
fmt.Fprint(p.Output, out)
|
||||
} else {
|
||||
fmt.Print(out)
|
||||
}
|
||||
p.lastBarsCount = len(p.bars)
|
||||
return isFinished
|
||||
}
|
||||
43
vendor/github.com/cheggaaa/pb/v3/pool_x.go
generated
vendored
Normal file
43
vendor/github.com/cheggaaa/pb/v3/pool_x.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly plan9 aix
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/cheggaaa/pb/v3/termutil"
|
||||
)
|
||||
|
||||
func (p *Pool) print(first bool) bool {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
var out string
|
||||
if !first {
|
||||
out = fmt.Sprintf("\033[%dA", p.lastBarsCount)
|
||||
}
|
||||
isFinished := true
|
||||
bars := p.bars
|
||||
rows, cols, err := termutil.TerminalSize()
|
||||
if err != nil {
|
||||
cols = defaultBarWidth
|
||||
}
|
||||
if rows > 0 && len(bars) > rows {
|
||||
// we need to hide bars that overflow terminal height
|
||||
bars = bars[len(bars)-rows:]
|
||||
}
|
||||
for _, bar := range bars {
|
||||
if !bar.IsFinished() {
|
||||
isFinished = false
|
||||
}
|
||||
bar.SetWidth(cols)
|
||||
out += fmt.Sprintf("\r%s\n", bar.String())
|
||||
}
|
||||
if p.Output != nil {
|
||||
fmt.Fprint(p.Output, out)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, out)
|
||||
}
|
||||
p.lastBarsCount = len(bars)
|
||||
return isFinished
|
||||
}
|
||||
15
vendor/github.com/cheggaaa/pb/v3/preset.go
generated
vendored
Normal file
15
vendor/github.com/cheggaaa/pb/v3/preset.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package pb
|
||||
|
||||
var (
|
||||
// Full - preset with all default available elements
|
||||
// Example: 'Prefix 20/100 [-->______] 20% 1 p/s ETA 1m Suffix'
|
||||
Full ProgressBarTemplate = `{{with string . "prefix"}}{{.}} {{end}}{{counters . }} {{bar . }} {{percent . }} {{speed . }} {{rtime . "ETA %s"}}{{with string . "suffix"}} {{.}}{{end}}`
|
||||
|
||||
// Default - preset like Full but without elapsed time
|
||||
// Example: 'Prefix 20/100 [-->______] 20% 1 p/s Suffix'
|
||||
Default ProgressBarTemplate = `{{with string . "prefix"}}{{.}} {{end}}{{counters . }} {{bar . }} {{percent . }} {{speed . }}{{with string . "suffix"}} {{.}}{{end}}`
|
||||
|
||||
// Simple - preset without speed and any timers. Only counters, bar and percents
|
||||
// Example: 'Prefix 20/100 [-->______] 20% Suffix'
|
||||
Simple ProgressBarTemplate = `{{with string . "prefix"}}{{.}} {{end}}{{counters . }} {{bar . }} {{percent . }}{{with string . "suffix"}} {{.}}{{end}}`
|
||||
)
|
||||
83
vendor/github.com/cheggaaa/pb/v3/speed.go
generated
vendored
Normal file
83
vendor/github.com/cheggaaa/pb/v3/speed.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/VividCortex/ewma"
|
||||
)
|
||||
|
||||
var speedAddLimit = time.Second / 2
|
||||
|
||||
type speed struct {
|
||||
ewma ewma.MovingAverage
|
||||
lastStateId uint64
|
||||
prevValue, startValue int64
|
||||
prevTime, startTime time.Time
|
||||
}
|
||||
|
||||
func (s *speed) value(state *State) float64 {
|
||||
if s.ewma == nil {
|
||||
s.ewma = ewma.NewMovingAverage()
|
||||
}
|
||||
if state.IsFirst() || state.Id() < s.lastStateId {
|
||||
s.reset(state)
|
||||
return 0
|
||||
}
|
||||
if state.Id() == s.lastStateId {
|
||||
return s.ewma.Value()
|
||||
}
|
||||
if state.IsFinished() {
|
||||
return s.absValue(state)
|
||||
}
|
||||
dur := state.Time().Sub(s.prevTime)
|
||||
if dur < speedAddLimit {
|
||||
return s.ewma.Value()
|
||||
}
|
||||
diff := math.Abs(float64(state.Value() - s.prevValue))
|
||||
lastSpeed := diff / dur.Seconds()
|
||||
s.prevTime = state.Time()
|
||||
s.prevValue = state.Value()
|
||||
s.lastStateId = state.Id()
|
||||
s.ewma.Add(lastSpeed)
|
||||
return s.ewma.Value()
|
||||
}
|
||||
|
||||
func (s *speed) reset(state *State) {
|
||||
s.lastStateId = state.Id()
|
||||
s.startTime = state.Time()
|
||||
s.prevTime = state.Time()
|
||||
s.startValue = state.Value()
|
||||
s.prevValue = state.Value()
|
||||
s.ewma = ewma.NewMovingAverage()
|
||||
}
|
||||
|
||||
func (s *speed) absValue(state *State) float64 {
|
||||
if dur := state.Time().Sub(s.startTime); dur > 0 {
|
||||
return float64(state.Value()) / dur.Seconds()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getSpeedObj(state *State) (s *speed) {
|
||||
if sObj, ok := state.Get(speedObj).(*speed); ok {
|
||||
return sObj
|
||||
}
|
||||
s = new(speed)
|
||||
state.Set(speedObj, s)
|
||||
return
|
||||
}
|
||||
|
||||
// ElementSpeed calculates current speed by EWMA
|
||||
// Optionally can take one or two string arguments.
|
||||
// First string will be used as value for format speed, default is "%s p/s".
|
||||
// Second string will be used when speed not available, default is "? p/s"
|
||||
// In template use as follows: {{speed .}} or {{speed . "%s per second"}} or {{speed . "%s ps" "..."}
|
||||
var ElementSpeed ElementFunc = func(state *State, args ...string) string {
|
||||
sp := getSpeedObj(state).value(state)
|
||||
if sp == 0 {
|
||||
return argsHelper(args).getNotEmptyOr(1, "? p/s")
|
||||
}
|
||||
return fmt.Sprintf(argsHelper(args).getNotEmptyOr(0, "%s p/s"), state.Format(int64(round(sp))))
|
||||
}
|
||||
89
vendor/github.com/cheggaaa/pb/v3/template.go
generated
vendored
Normal file
89
vendor/github.com/cheggaaa/pb/v3/template.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// ProgressBarTemplate that template string
|
||||
type ProgressBarTemplate string
|
||||
|
||||
// New creates new bar from template
|
||||
func (pbt ProgressBarTemplate) New(total int) *ProgressBar {
|
||||
return New(total).SetTemplate(pbt)
|
||||
}
|
||||
|
||||
// Start64 create and start new bar with given int64 total value
|
||||
func (pbt ProgressBarTemplate) Start64(total int64) *ProgressBar {
|
||||
return New64(total).SetTemplate(pbt).Start()
|
||||
}
|
||||
|
||||
// Start create and start new bar with given int total value
|
||||
func (pbt ProgressBarTemplate) Start(total int) *ProgressBar {
|
||||
return pbt.Start64(int64(total))
|
||||
}
|
||||
|
||||
var templateCacheMu sync.Mutex
|
||||
var templateCache = make(map[string]*template.Template)
|
||||
|
||||
var defaultTemplateFuncs = template.FuncMap{
|
||||
// colors
|
||||
"black": color.New(color.FgBlack).SprintFunc(),
|
||||
"red": color.New(color.FgRed).SprintFunc(),
|
||||
"green": color.New(color.FgGreen).SprintFunc(),
|
||||
"yellow": color.New(color.FgYellow).SprintFunc(),
|
||||
"blue": color.New(color.FgBlue).SprintFunc(),
|
||||
"magenta": color.New(color.FgMagenta).SprintFunc(),
|
||||
"cyan": color.New(color.FgCyan).SprintFunc(),
|
||||
"white": color.New(color.FgWhite).SprintFunc(),
|
||||
"resetcolor": color.New(color.Reset).SprintFunc(),
|
||||
"rndcolor": rndcolor,
|
||||
"rnd": rnd,
|
||||
}
|
||||
|
||||
func getTemplate(tmpl string) (t *template.Template, err error) {
|
||||
templateCacheMu.Lock()
|
||||
defer templateCacheMu.Unlock()
|
||||
t = templateCache[tmpl]
|
||||
if t != nil {
|
||||
// found in cache
|
||||
return
|
||||
}
|
||||
t = template.New("")
|
||||
fillTemplateFuncs(t)
|
||||
_, err = t.Parse(tmpl)
|
||||
if err != nil {
|
||||
t = nil
|
||||
return
|
||||
}
|
||||
templateCache[tmpl] = t
|
||||
return
|
||||
}
|
||||
|
||||
func fillTemplateFuncs(t *template.Template) {
|
||||
t.Funcs(defaultTemplateFuncs)
|
||||
emf := make(template.FuncMap)
|
||||
elementsM.Lock()
|
||||
for k, v := range elements {
|
||||
element := v
|
||||
emf[k] = func(state *State, args ...string) string { return element.ProgressElement(state, args...) }
|
||||
}
|
||||
elementsM.Unlock()
|
||||
t.Funcs(emf)
|
||||
return
|
||||
}
|
||||
|
||||
func rndcolor(s string) string {
|
||||
c := rand.Intn(int(color.FgWhite-color.FgBlack)) + int(color.FgBlack)
|
||||
return color.New(color.Attribute(c)).Sprint(s)
|
||||
}
|
||||
|
||||
func rnd(args ...string) string {
|
||||
if len(args) == 0 {
|
||||
return ""
|
||||
}
|
||||
return args[rand.Intn(len(args))]
|
||||
}
|
||||
68
vendor/github.com/cheggaaa/pb/v3/termutil/term.go
generated
vendored
Normal file
68
vendor/github.com/cheggaaa/pb/v3/termutil/term.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package termutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var echoLocked bool
|
||||
var echoLockMutex sync.Mutex
|
||||
var errLocked = errors.New("terminal locked")
|
||||
var autoTerminate = true
|
||||
|
||||
// AutoTerminate enables or disables automatic terminate signal catching.
|
||||
// It's needed to restore the terminal state after the pool was used.
|
||||
// By default, it's enabled.
|
||||
func AutoTerminate(enable bool) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
autoTerminate = enable
|
||||
}
|
||||
|
||||
// RawModeOn switches terminal to raw mode
|
||||
func RawModeOn() (quit chan struct{}, err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if echoLocked {
|
||||
err = errLocked
|
||||
return
|
||||
}
|
||||
if err = lockEcho(); err != nil {
|
||||
return
|
||||
}
|
||||
echoLocked = true
|
||||
quit = make(chan struct{}, 1)
|
||||
go catchTerminate(quit)
|
||||
return
|
||||
}
|
||||
|
||||
// RawModeOff restore previous terminal state
|
||||
func RawModeOff() (err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if !echoLocked {
|
||||
return
|
||||
}
|
||||
if err = unlockEcho(); err != nil {
|
||||
return
|
||||
}
|
||||
echoLocked = false
|
||||
return
|
||||
}
|
||||
|
||||
// listen exit signals and restore terminal state
|
||||
func catchTerminate(quit chan struct{}) {
|
||||
sig := make(chan os.Signal, 1)
|
||||
if autoTerminate {
|
||||
signal.Notify(sig, unlockSignals...)
|
||||
defer signal.Stop(sig)
|
||||
}
|
||||
select {
|
||||
case <-quit:
|
||||
RawModeOff()
|
||||
case <-sig:
|
||||
RawModeOff()
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/cheggaaa/pb/v3/termutil/term_appengine.go
generated
vendored
Normal file
12
vendor/github.com/cheggaaa/pb/v3/termutil/term_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package termutil
|
||||
|
||||
import "errors"
|
||||
|
||||
// terminalWidth returns width of the terminal, which is not supported
|
||||
// and should always failed on appengine classic which is a sandboxed PaaS.
|
||||
func TerminalWidth() (int, error) {
|
||||
return 0, errors.New("Not supported")
|
||||
}
|
||||
10
vendor/github.com/cheggaaa/pb/v3/termutil/term_bsd.go
generated
vendored
Normal file
10
vendor/github.com/cheggaaa/pb/v3/termutil/term_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
//go:build (darwin || freebsd || netbsd || openbsd || dragonfly) && !appengine
|
||||
// +build darwin freebsd netbsd openbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package termutil
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
const ioctlWriteTermios = syscall.TIOCSETA
|
||||
7
vendor/github.com/cheggaaa/pb/v3/termutil/term_linux.go
generated
vendored
Normal file
7
vendor/github.com/cheggaaa/pb/v3/termutil/term_linux.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build linux && !appengine
|
||||
// +build linux,!appengine
|
||||
|
||||
package termutil
|
||||
|
||||
const ioctlReadTermios = 0x5401 // syscall.TCGETS
|
||||
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
|
||||
9
vendor/github.com/cheggaaa/pb/v3/termutil/term_nix.go
generated
vendored
Normal file
9
vendor/github.com/cheggaaa/pb/v3/termutil/term_nix.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
//go:build (linux || darwin || freebsd || netbsd || openbsd || dragonfly) && !appengine
|
||||
// +build linux darwin freebsd netbsd openbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package termutil
|
||||
|
||||
import "syscall"
|
||||
|
||||
const sysIoctl = syscall.SYS_IOCTL
|
||||
50
vendor/github.com/cheggaaa/pb/v3/termutil/term_plan9.go
generated
vendored
Normal file
50
vendor/github.com/cheggaaa/pb/v3/termutil/term_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package termutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
consctl *os.File
|
||||
|
||||
// Plan 9 doesn't have syscall.SIGQUIT
|
||||
unlockSignals = []os.Signal{
|
||||
os.Interrupt, syscall.SIGTERM, syscall.SIGKILL,
|
||||
}
|
||||
)
|
||||
|
||||
// TerminalWidth returns width of the terminal.
|
||||
func TerminalWidth() (int, error) {
|
||||
return 0, errors.New("Not supported")
|
||||
}
|
||||
|
||||
func lockEcho() error {
|
||||
if consctl != nil {
|
||||
return errors.New("consctl already open")
|
||||
}
|
||||
var err error
|
||||
consctl, err = os.OpenFile("/dev/consctl", os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = consctl.WriteString("rawon")
|
||||
if err != nil {
|
||||
consctl.Close()
|
||||
consctl = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockEcho() error {
|
||||
if consctl == nil {
|
||||
return nil
|
||||
}
|
||||
if err := consctl.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
consctl = nil
|
||||
return nil
|
||||
}
|
||||
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_solaris.go
generated
vendored
Normal file
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build solaris && !appengine
|
||||
// +build solaris,!appengine
|
||||
|
||||
package termutil
|
||||
|
||||
const ioctlReadTermios = 0x5401 // syscall.TCGETS
|
||||
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
|
||||
const sysIoctl = 54
|
||||
156
vendor/github.com/cheggaaa/pb/v3/termutil/term_win.go
generated
vendored
Normal file
156
vendor/github.com/cheggaaa/pb/v3/termutil/term_win.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package termutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
tty = os.Stdin
|
||||
|
||||
unlockSignals = []os.Signal{
|
||||
os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
// GetConsoleScreenBufferInfo retrieves information about the
|
||||
// specified console screen buffer.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
|
||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
|
||||
// GetConsoleMode retrieves the current input mode of a console's
|
||||
// input buffer or the current output mode of a console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
|
||||
getConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
|
||||
// SetConsoleMode sets the input mode of a console's input buffer
|
||||
// or the output mode of a console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
setConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||
|
||||
// SetConsoleCursorPosition sets the cursor position in the
|
||||
// specified console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx
|
||||
setConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
|
||||
|
||||
mingw = isMingw()
|
||||
)
|
||||
|
||||
type (
|
||||
// Defines the coordinates of the upper left and lower right corners
|
||||
// of a rectangle.
|
||||
// See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311(v=vs.85).aspx
|
||||
smallRect struct {
|
||||
Left, Top, Right, Bottom int16
|
||||
}
|
||||
|
||||
// Defines the coordinates of a character cell in a console screen
|
||||
// buffer. The origin of the coordinate system (0,0) is at the top, left cell
|
||||
// of the buffer.
|
||||
// See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx
|
||||
coordinates struct {
|
||||
X, Y int16
|
||||
}
|
||||
|
||||
word int16
|
||||
|
||||
// Contains information about a console screen buffer.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
|
||||
consoleScreenBufferInfo struct {
|
||||
dwSize coordinates
|
||||
dwCursorPosition coordinates
|
||||
wAttributes word
|
||||
srWindow smallRect
|
||||
dwMaximumWindowSize coordinates
|
||||
}
|
||||
)
|
||||
|
||||
// TerminalWidth returns width of the terminal.
|
||||
func TerminalWidth() (width int, err error) {
|
||||
if mingw {
|
||||
return termWidthTPut()
|
||||
}
|
||||
return termWidthCmd()
|
||||
}
|
||||
|
||||
func termWidthCmd() (width int, err error) {
|
||||
var info consoleScreenBufferInfo
|
||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
|
||||
if e != 0 {
|
||||
return 0, error(e)
|
||||
}
|
||||
return int(info.dwSize.X) - 1, nil
|
||||
}
|
||||
|
||||
func isMingw() bool {
|
||||
return os.Getenv("MINGW_PREFIX") != "" || os.Getenv("MSYSTEM") == "MINGW64"
|
||||
}
|
||||
|
||||
func termWidthTPut() (width int, err error) {
|
||||
// TODO: maybe anybody knows a better way to get it on mintty...
|
||||
var res []byte
|
||||
cmd := exec.Command("tput", "cols")
|
||||
cmd.Stdin = os.Stdin
|
||||
if res, err = cmd.CombinedOutput(); err != nil {
|
||||
return 0, fmt.Errorf("%s: %v", string(res), err)
|
||||
}
|
||||
if len(res) > 1 {
|
||||
res = res[:len(res)-1]
|
||||
}
|
||||
return strconv.Atoi(string(res))
|
||||
}
|
||||
|
||||
func GetCursorPos() (pos coordinates, err error) {
|
||||
var info consoleScreenBufferInfo
|
||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
|
||||
if e != 0 {
|
||||
return info.dwCursorPosition, error(e)
|
||||
}
|
||||
return info.dwCursorPosition, nil
|
||||
}
|
||||
|
||||
func SetCursorPos(pos coordinates) error {
|
||||
_, _, e := syscall.Syscall(setConsoleCursorPosition.Addr(), 2, uintptr(syscall.Stdout), uintptr(uint32(uint16(pos.Y))<<16|uint32(uint16(pos.X))), 0)
|
||||
if e != 0 {
|
||||
return error(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldState word
|
||||
|
||||
func lockEcho() (err error) {
|
||||
if _, _, e := syscall.Syscall(getConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&oldState)), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't get terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
|
||||
newState := oldState
|
||||
const ENABLE_ECHO_INPUT = 0x0004
|
||||
const ENABLE_LINE_INPUT = 0x0002
|
||||
newState = newState & (^(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
|
||||
if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(newState), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unlockEcho() (err error) {
|
||||
if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(oldState), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings")
|
||||
}
|
||||
return
|
||||
}
|
||||
81
vendor/github.com/cheggaaa/pb/v3/termutil/term_x.go
generated
vendored
Normal file
81
vendor/github.com/cheggaaa/pb/v3/termutil/term_x.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//go:build (linux || darwin || freebsd || netbsd || openbsd || solaris || dragonfly) && !appengine
|
||||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package termutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
tty *os.File
|
||||
|
||||
unlockSignals = []os.Signal{
|
||||
os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL,
|
||||
}
|
||||
oldState syscall.Termios
|
||||
)
|
||||
|
||||
type window struct {
|
||||
Row uint16
|
||||
Col uint16
|
||||
Xpixel uint16
|
||||
Ypixel uint16
|
||||
}
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
tty, err = os.Open("/dev/tty")
|
||||
if err != nil {
|
||||
tty = os.Stdin
|
||||
}
|
||||
}
|
||||
|
||||
// TerminalWidth returns width of the terminal.
|
||||
func TerminalWidth() (int, error) {
|
||||
_, c, err := TerminalSize()
|
||||
return c, err
|
||||
}
|
||||
|
||||
// TerminalSize returns size of the terminal.
|
||||
func TerminalSize() (rows, cols int, err error) {
|
||||
w := new(window)
|
||||
res, _, err := syscall.Syscall(sysIoctl,
|
||||
tty.Fd(),
|
||||
uintptr(syscall.TIOCGWINSZ),
|
||||
uintptr(unsafe.Pointer(w)),
|
||||
)
|
||||
if int(res) == -1 {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(w.Row), int(w.Col), nil
|
||||
}
|
||||
|
||||
func lockEcho() error {
|
||||
fd := tty.Fd()
|
||||
|
||||
if _, _, err := syscall.Syscall(sysIoctl, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&oldState))); err != 0 {
|
||||
return fmt.Errorf("error when puts the terminal connected to the given file descriptor: %w", err)
|
||||
}
|
||||
|
||||
newState := oldState
|
||||
newState.Lflag &^= syscall.ECHO
|
||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
||||
newState.Iflag |= syscall.ICRNL
|
||||
if _, _, e := syscall.Syscall(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&newState))); e != 0 {
|
||||
return fmt.Errorf("error update terminal settings: %w", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockEcho() error {
|
||||
fd := tty.Fd()
|
||||
if _, _, err := syscall.Syscall(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState))); err != 0 {
|
||||
return fmt.Errorf("error restores the terminal connected to the given file descriptor: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
116
vendor/github.com/cheggaaa/pb/v3/util.go
generated
vendored
Normal file
116
vendor/github.com/cheggaaa/pb/v3/util.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/mattn/go-runewidth"
|
||||
"math"
|
||||
"regexp"
|
||||
//"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
_KiB = 1024
|
||||
_MiB = 1048576
|
||||
_GiB = 1073741824
|
||||
_TiB = 1099511627776
|
||||
|
||||
_kB = 1e3
|
||||
_MB = 1e6
|
||||
_GB = 1e9
|
||||
_TB = 1e12
|
||||
)
|
||||
|
||||
var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9;]+\x6d")
|
||||
|
||||
func CellCount(s string) int {
|
||||
n := runewidth.StringWidth(s)
|
||||
for _, sm := range ctrlFinder.FindAllString(s, -1) {
|
||||
n -= runewidth.StringWidth(sm)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func StripString(s string, w int) string {
|
||||
l := CellCount(s)
|
||||
if l <= w {
|
||||
return s
|
||||
}
|
||||
var buf = bytes.NewBuffer(make([]byte, 0, len(s)))
|
||||
StripStringToBuffer(s, w, buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func StripStringToBuffer(s string, w int, buf *bytes.Buffer) {
|
||||
var seqs = ctrlFinder.FindAllStringIndex(s, -1)
|
||||
var maxWidthReached bool
|
||||
mainloop:
|
||||
for i, r := range s {
|
||||
for _, seq := range seqs {
|
||||
if i >= seq[0] && i < seq[1] {
|
||||
buf.WriteRune(r)
|
||||
continue mainloop
|
||||
}
|
||||
}
|
||||
if rw := CellCount(string(r)); rw <= w && !maxWidthReached {
|
||||
w -= rw
|
||||
buf.WriteRune(r)
|
||||
} else {
|
||||
maxWidthReached = true
|
||||
}
|
||||
}
|
||||
for w > 0 {
|
||||
buf.WriteByte(' ')
|
||||
w--
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func round(val float64) (newVal float64) {
|
||||
roundOn := 0.5
|
||||
places := 0
|
||||
var round float64
|
||||
pow := math.Pow(10, float64(places))
|
||||
digit := pow * val
|
||||
_, div := math.Modf(digit)
|
||||
if div >= roundOn {
|
||||
round = math.Ceil(digit)
|
||||
} else {
|
||||
round = math.Floor(digit)
|
||||
}
|
||||
newVal = round / pow
|
||||
return
|
||||
}
|
||||
|
||||
// Convert bytes to human readable string. Like a 2 MiB, 64.2 KiB, or 2 MB, 64.2 kB
|
||||
// if useSIPrefix is set to true
|
||||
func formatBytes(i int64, useSIPrefix bool) (result string) {
|
||||
if !useSIPrefix {
|
||||
switch {
|
||||
case i >= _TiB:
|
||||
result = fmt.Sprintf("%.02f TiB", float64(i)/_TiB)
|
||||
case i >= _GiB:
|
||||
result = fmt.Sprintf("%.02f GiB", float64(i)/_GiB)
|
||||
case i >= _MiB:
|
||||
result = fmt.Sprintf("%.02f MiB", float64(i)/_MiB)
|
||||
case i >= _KiB:
|
||||
result = fmt.Sprintf("%.02f KiB", float64(i)/_KiB)
|
||||
default:
|
||||
result = fmt.Sprintf("%d B", i)
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case i >= _TB:
|
||||
result = fmt.Sprintf("%.02f TB", float64(i)/_TB)
|
||||
case i >= _GB:
|
||||
result = fmt.Sprintf("%.02f GB", float64(i)/_GB)
|
||||
case i >= _MB:
|
||||
result = fmt.Sprintf("%.02f MB", float64(i)/_MB)
|
||||
case i >= _kB:
|
||||
result = fmt.Sprintf("%.02f kB", float64(i)/_kB)
|
||||
default:
|
||||
result = fmt.Sprintf("%d B", i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
117
vendor/github.com/docker/docker/AUTHORS
generated
vendored
117
vendor/github.com/docker/docker/AUTHORS
generated
vendored
@@ -4,6 +4,7 @@
|
||||
Aanand Prasad <aanand.prasad@gmail.com>
|
||||
Aaron Davidson <aaron@databricks.com>
|
||||
Aaron Feng <aaron.feng@gmail.com>
|
||||
Aaron Hnatiw <aaron@griddio.com>
|
||||
Aaron Huslage <huslage@gmail.com>
|
||||
Aaron L. Xu <liker.xu@foxmail.com>
|
||||
Aaron Lehmann <aaron.lehmann@docker.com>
|
||||
@@ -17,6 +18,7 @@ Abhishek Chanda <abhishek.becs@gmail.com>
|
||||
Abhishek Sharma <abhishek@asharma.me>
|
||||
Abin Shahab <ashahab@altiscale.com>
|
||||
Adam Avilla <aavilla@yp.com>
|
||||
Adam Dobrawy <naczelnik@jawnosc.tk>
|
||||
Adam Eijdenberg <adam.eijdenberg@gmail.com>
|
||||
Adam Kunk <adam.kunk@tiaa-cref.org>
|
||||
Adam Miller <admiller@redhat.com>
|
||||
@@ -43,6 +45,7 @@ AJ Bowen <aj@soulshake.net>
|
||||
Ajey Charantimath <ajey.charantimath@gmail.com>
|
||||
ajneu <ajneu@users.noreply.github.com>
|
||||
Akash Gupta <akagup@microsoft.com>
|
||||
Akhil Mohan <akhil.mohan@mayadata.io>
|
||||
Akihiro Matsushima <amatsusbit@gmail.com>
|
||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
|
||||
Akim Demaille <akim.demaille@docker.com>
|
||||
@@ -50,10 +53,12 @@ Akira Koyasu <mail@akirakoyasu.net>
|
||||
Akshay Karle <akshay.a.karle@gmail.com>
|
||||
Al Tobey <al@ooyala.com>
|
||||
alambike <alambike@gmail.com>
|
||||
Alan Hoyle <alan@alanhoyle.com>
|
||||
Alan Scherger <flyinprogrammer@gmail.com>
|
||||
Alan Thompson <cloojure@gmail.com>
|
||||
Albert Callarisa <shark234@gmail.com>
|
||||
Albert Zhang <zhgwenming@gmail.com>
|
||||
Albin Kerouanton <albin@akerouanton.name>
|
||||
Alejandro González Hevia <alejandrgh11@gmail.com>
|
||||
Aleksa Sarai <asarai@suse.de>
|
||||
Aleksandrs Fadins <aleks@s-ko.net>
|
||||
@@ -107,11 +112,13 @@ Amy Lindburg <amy.lindburg@docker.com>
|
||||
Anand Patil <anand.prabhakar.patil@gmail.com>
|
||||
AnandkumarPatel <anandkumarpatel@gmail.com>
|
||||
Anatoly Borodin <anatoly.borodin@gmail.com>
|
||||
Anca Iordache <anca.iordache@docker.com>
|
||||
Anchal Agrawal <aagrawa4@illinois.edu>
|
||||
Anda Xu <anda.xu@docker.com>
|
||||
Anders Janmyr <anders@janmyr.com>
|
||||
Andre Dublin <81dublin@gmail.com>
|
||||
Andre Granovsky <robotciti@live.com>
|
||||
Andrea Denisse Gómez <crypto.andrea@protonmail.ch>
|
||||
Andrea Luzzardi <aluzzardi@gmail.com>
|
||||
Andrea Turli <andrea.turli@gmail.com>
|
||||
Andreas Elvers <andreas@work.de>
|
||||
@@ -176,8 +183,10 @@ Anusha Ragunathan <anusha.ragunathan@docker.com>
|
||||
apocas <petermdias@gmail.com>
|
||||
Arash Deshmeh <adeshmeh@ca.ibm.com>
|
||||
ArikaChen <eaglesora@gmail.com>
|
||||
Arko Dasgupta <arko.dasgupta@docker.com>
|
||||
Arnaud Lefebvre <a.lefebvre@outlook.fr>
|
||||
Arnaud Porterie <arnaud.porterie@docker.com>
|
||||
Arnaud Rebillout <arnaud.rebillout@collabora.com>
|
||||
Arthur Barr <arthur.barr@uk.ibm.com>
|
||||
Arthur Gautier <baloo@gandi.net>
|
||||
Artur Meyster <arthurfbi@yahoo.com>
|
||||
@@ -210,10 +219,12 @@ Benjamin Atkin <ben@benatkin.com>
|
||||
Benjamin Baker <Benjamin.baker@utexas.edu>
|
||||
Benjamin Boudreau <boudreau.benjamin@gmail.com>
|
||||
Benjamin Yolken <yolken@stripe.com>
|
||||
Benny Ng <benny.tpng@gmail.com>
|
||||
Benoit Chesneau <bchesneau@gmail.com>
|
||||
Bernerd Schaefer <bj.schaefer@gmail.com>
|
||||
Bernhard M. Wiedemann <bwiedemann@suse.de>
|
||||
Bert Goethals <bert@bertg.be>
|
||||
Bertrand Roussel <broussel@sierrawireless.com>
|
||||
Bevisy Zhang <binbin36520@gmail.com>
|
||||
Bharath Thiruveedula <bharath_ves@hotmail.com>
|
||||
Bhiraj Butala <abhiraj.butala@gmail.com>
|
||||
@@ -226,6 +237,7 @@ Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
||||
Blake Geno <blakegeno@gmail.com>
|
||||
Boaz Shuster <ripcurld.github@gmail.com>
|
||||
bobby abbott <ttobbaybbob@gmail.com>
|
||||
Boqin Qin <bobbqqin@gmail.com>
|
||||
Boris Pruessmann <boris@pruessmann.org>
|
||||
Boshi Lian <farmer1992@gmail.com>
|
||||
Bouke Haarsma <bouke@webatoom.nl>
|
||||
@@ -279,6 +291,7 @@ Carl Loa Odin <carlodin@gmail.com>
|
||||
Carl X. Su <bcbcarl@gmail.com>
|
||||
Carlo Mion <mion00@gmail.com>
|
||||
Carlos Alexandro Becker <caarlos0@gmail.com>
|
||||
Carlos de Paula <me@carlosedp.com>
|
||||
Carlos Sanchez <carlos@apache.org>
|
||||
Carol Fager-Higgins <carol.fager-higgins@docker.com>
|
||||
Cary <caryhartline@users.noreply.github.com>
|
||||
@@ -328,6 +341,7 @@ Chris Gibson <chris@chrisg.io>
|
||||
Chris Khoo <chris.khoo@gmail.com>
|
||||
Chris McKinnel <chris.mckinnel@tangentlabs.co.uk>
|
||||
Chris McKinnel <chrismckinnel@gmail.com>
|
||||
Chris Price <cprice@mirantis.com>
|
||||
Chris Seto <chriskseto@gmail.com>
|
||||
Chris Snow <chsnow123@gmail.com>
|
||||
Chris St. Pierre <chris.a.st.pierre@gmail.com>
|
||||
@@ -354,7 +368,7 @@ Christopher Currie <codemonkey+github@gmail.com>
|
||||
Christopher Jones <tophj@linux.vnet.ibm.com>
|
||||
Christopher Latham <sudosurootdev@gmail.com>
|
||||
Christopher Rigor <crigor@gmail.com>
|
||||
Christy Perez <christy@linux.vnet.ibm.com>
|
||||
Christy Norman <christy@linux.vnet.ibm.com>
|
||||
Chun Chen <ramichen@tencent.com>
|
||||
Ciro S. Costa <ciro.costa@usp.br>
|
||||
Clayton Coleman <ccoleman@redhat.com>
|
||||
@@ -374,8 +388,10 @@ Corey Farrell <git@cfware.com>
|
||||
Cory Forsyth <cory.forsyth@gmail.com>
|
||||
cressie176 <github@stephen-cresswell.net>
|
||||
CrimsonGlory <CrimsonGlory@users.noreply.github.com>
|
||||
Cristian Ariza <dev@cristianrz.com>
|
||||
Cristian Staretu <cristian.staretu@gmail.com>
|
||||
cristiano balducci <cristiano.balducci@gmail.com>
|
||||
Cristina Yenyxe Gonzalez Garcia <cristina.yenyxe@gmail.com>
|
||||
Cruceru Calin-Cristian <crucerucalincristian@gmail.com>
|
||||
CUI Wei <ghostplant@qq.com>
|
||||
Cyprian Gracz <cyprian.gracz@micro-jumbo.eu>
|
||||
@@ -402,12 +418,14 @@ Dan Williams <me@deedubs.com>
|
||||
Dani Hodovic <dani.hodovic@gmail.com>
|
||||
Dani Louca <dani.louca@docker.com>
|
||||
Daniel Antlinger <d.antlinger@gmx.at>
|
||||
Daniel Black <daniel@linux.ibm.com>
|
||||
Daniel Dao <dqminh@cloudflare.com>
|
||||
Daniel Exner <dex@dragonslave.de>
|
||||
Daniel Farrell <dfarrell@redhat.com>
|
||||
Daniel Garcia <daniel@danielgarcia.info>
|
||||
Daniel Gasienica <daniel@gasienica.ch>
|
||||
Daniel Grunwell <mwgrunny@gmail.com>
|
||||
Daniel Helfand <helfand.4@gmail.com>
|
||||
Daniel Hiltgen <daniel.hiltgen@docker.com>
|
||||
Daniel J Walsh <dwalsh@redhat.com>
|
||||
Daniel Menet <membership@sontags.ch>
|
||||
@@ -417,12 +435,14 @@ Daniel Norberg <dano@spotify.com>
|
||||
Daniel Nordberg <dnordberg@gmail.com>
|
||||
Daniel Robinson <gottagetmac@gmail.com>
|
||||
Daniel S <dan.streby@gmail.com>
|
||||
Daniel Sweet <danieljsweet@icloud.com>
|
||||
Daniel Von Fange <daniel@leancoder.com>
|
||||
Daniel Watkins <daniel@daniel-watkins.co.uk>
|
||||
Daniel X Moore <yahivin@gmail.com>
|
||||
Daniel YC Lin <dlin.tw@gmail.com>
|
||||
Daniel Zhang <jmzwcn@gmail.com>
|
||||
Danny Berger <dpb587@gmail.com>
|
||||
Danny Milosavljevic <dannym@scratchpost.org>
|
||||
Danny Yates <danny@codeaholics.org>
|
||||
Danyal Khaliq <danyal.khaliq@tenpearls.com>
|
||||
Darren Coxall <darren@darrencoxall.com>
|
||||
@@ -487,6 +507,7 @@ Derek McGowan <derek@mcgstyle.net>
|
||||
Deric Crago <deric.crago@gmail.com>
|
||||
Deshi Xiao <dxiao@redhat.com>
|
||||
devmeyster <arthurfbi@yahoo.com>
|
||||
Devon Estes <devon.estes@klarna.com>
|
||||
Devvyn Murphy <devvyn@devvyn.com>
|
||||
Dharmit Shah <shahdharmit@gmail.com>
|
||||
Dhawal Yogesh Bhanushali <dbhanushali@vmware.com>
|
||||
@@ -516,6 +537,8 @@ Dmitry Smirnov <onlyjob@member.fsf.org>
|
||||
Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
|
||||
Dmitry Vorobev <dimahabr@gmail.com>
|
||||
Dolph Mathews <dolph.mathews@gmail.com>
|
||||
Dominic Tubach <dominic.tubach@to.com>
|
||||
Dominic Yin <yindongchao@inspur.com>
|
||||
Dominik Dingel <dingel@linux.vnet.ibm.com>
|
||||
Dominik Finkbeiner <finkes93@gmail.com>
|
||||
Dominik Honnef <dominik@honnef.co>
|
||||
@@ -534,7 +557,7 @@ Douglas Curtis <dougcurtis1@gmail.com>
|
||||
Dr Nic Williams <drnicwilliams@gmail.com>
|
||||
dragon788 <dragon788@users.noreply.github.com>
|
||||
Dražen Lučanin <kermit666@gmail.com>
|
||||
Drew Erny <drew.erny@docker.com>
|
||||
Drew Erny <derny@mirantis.com>
|
||||
Drew Hubl <drew.hubl@gmail.com>
|
||||
Dustin Sallings <dustin@spy.net>
|
||||
Ed Costello <epc@epcostello.com>
|
||||
@@ -584,6 +607,7 @@ Erik Weathers <erikdw@gmail.com>
|
||||
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
||||
Erwin van der Koogh <info@erronis.nl>
|
||||
Ethan Bell <ebgamer29@gmail.com>
|
||||
Ethan Mosbaugh <ethan@replicated.com>
|
||||
Euan Kemp <euan.kemp@coreos.com>
|
||||
Eugen Krizo <eugen.krizo@gmail.com>
|
||||
Eugene Yakubovich <eugene.yakubovich@coreos.com>
|
||||
@@ -595,6 +619,7 @@ Evan Phoenix <evan@fallingsnow.net>
|
||||
Evan Wies <evan@neomantra.net>
|
||||
Evelyn Xu <evelynhsu21@gmail.com>
|
||||
Everett Toews <everett.toews@rackspace.com>
|
||||
Evgeniy Makhrov <e.makhrov@corp.badoo.com>
|
||||
Evgeny Shmarnev <shmarnev@gmail.com>
|
||||
Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Ewa Czechowska <ewa@ai-traders.com>
|
||||
@@ -620,6 +645,7 @@ Fareed Dudhia <fareeddudhia@googlemail.com>
|
||||
Fathi Boudra <fathi.boudra@linaro.org>
|
||||
Federico Gimenez <fgimenez@coit.es>
|
||||
Felipe Oliveira <felipeweb.programador@gmail.com>
|
||||
Felipe Ruhland <felipe.ruhland@gmail.com>
|
||||
Felix Abecassis <fabecassis@nvidia.com>
|
||||
Felix Geisendörfer <felix@debuggable.com>
|
||||
Felix Hupfeld <felix@quobyte.com>
|
||||
@@ -640,6 +666,7 @@ Florian <FWirtz@users.noreply.github.com>
|
||||
Florian Klein <florian.klein@free.fr>
|
||||
Florian Maier <marsmensch@users.noreply.github.com>
|
||||
Florian Noeding <noeding@adobe.com>
|
||||
Florian Schmaus <flo@geekplace.eu>
|
||||
Florian Weingarten <flo@hackvalue.de>
|
||||
Florin Asavoaie <florin.asavoaie@gmail.com>
|
||||
Florin Patan <florinpatan@gmail.com>
|
||||
@@ -654,6 +681,7 @@ Frank Groeneveld <frank@ivaldi.nl>
|
||||
Frank Herrmann <fgh@4gh.tv>
|
||||
Frank Macreery <frank@macreery.com>
|
||||
Frank Rosquin <frank.rosquin+github@gmail.com>
|
||||
frankyang <yyb196@gmail.com>
|
||||
Fred Lifton <fred.lifton@docker.com>
|
||||
Frederick F. Kautz IV <fkautz@redhat.com>
|
||||
Frederik Loeffert <frederik@zitrusmedia.de>
|
||||
@@ -675,7 +703,7 @@ Gareth Rushgrove <gareth@morethanseven.net>
|
||||
Garrett Barboza <garrett@garrettbarboza.com>
|
||||
Gary Schaetz <gary@schaetzkc.com>
|
||||
Gaurav <gaurav.gosec@gmail.com>
|
||||
gautam, prasanna <prasannagautam@gmail.com>
|
||||
Gaurav Singh <gaurav1086@gmail.com>
|
||||
Gaël PORTAY <gael.portay@savoirfairelinux.com>
|
||||
Genki Takiuchi <genki@s21g.com>
|
||||
GennadySpb <lipenkov@gmail.com>
|
||||
@@ -701,11 +729,12 @@ Gleb M Borisov <borisov.gleb@gmail.com>
|
||||
Glyn Normington <gnormington@gopivotal.com>
|
||||
GoBella <caili_welcome@163.com>
|
||||
Goffert van Gool <goffert@phusion.nl>
|
||||
Goldwyn Rodrigues <rgoldwyn@suse.com>
|
||||
Gopikannan Venugopalsamy <gopikannan.venugopalsamy@gmail.com>
|
||||
Gosuke Miyashita <gosukenator@gmail.com>
|
||||
Gou Rao <gou@portworx.com>
|
||||
Govinda Fichtner <govinda.fichtner@googlemail.com>
|
||||
Grant Millar <grant@cylo.io>
|
||||
Grant Millar <rid@cylo.io>
|
||||
Grant Reaber <grant.reaber@gmail.com>
|
||||
Graydon Hoare <graydon@pobox.com>
|
||||
Greg Fausak <greg@tacodata.com>
|
||||
@@ -724,14 +753,17 @@ Guruprasad <lgp171188@gmail.com>
|
||||
Gustav Sinder <gustav.sinder@gmail.com>
|
||||
gwx296173 <gaojing3@huawei.com>
|
||||
Günter Zöchbauer <guenter@gzoechbauer.com>
|
||||
Haichao Yang <yang.haichao@zte.com.cn>
|
||||
haikuoliu <haikuo@amazon.com>
|
||||
Hakan Özler <hakan.ozler@kodcu.com>
|
||||
Hamish Hutchings <moredhel@aoeu.me>
|
||||
Hannes Ljungberg <hannes@5monkeys.se>
|
||||
Hans Kristian Flaatten <hans@starefossen.com>
|
||||
Hans Rødtang <hansrodtang@gmail.com>
|
||||
Hao Shu Wei <haosw@cn.ibm.com>
|
||||
Hao Zhang <21521210@zju.edu.cn>
|
||||
Harald Albers <github@albersweb.de>
|
||||
Harald Niesche <harald@niesche.de>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Harold Cooper <hrldcpr@gmail.com>
|
||||
Harrison Turton <harrisonturton@gmail.com>
|
||||
@@ -751,9 +783,13 @@ Hobofan <goisser94@gmail.com>
|
||||
Hollie Teal <hollie@docker.com>
|
||||
Hong Xu <hong@topbug.net>
|
||||
Hongbin Lu <hongbin034@gmail.com>
|
||||
Hongxu Jia <hongxu.jia@windriver.com>
|
||||
Honza Pokorny <me@honza.ca>
|
||||
Hsing-Hui Hsu <hsinghui@amazon.com>
|
||||
hsinko <21551195@zju.edu.cn>
|
||||
Hu Keping <hukeping@huawei.com>
|
||||
Hu Tao <hutao@cn.fujitsu.com>
|
||||
HuanHuan Ye <logindaveye@gmail.com>
|
||||
Huanzhong Zhang <zhanghuanzhong90@gmail.com>
|
||||
Huayi Zhang <irachex@gmail.com>
|
||||
Hugo Duncan <hugo@hugoduncan.org>
|
||||
@@ -790,6 +826,7 @@ Ingo Gottwald <in.gottwald@gmail.com>
|
||||
Innovimax <innovimax@gmail.com>
|
||||
Isaac Dupree <antispam@idupree.com>
|
||||
Isabel Jimenez <contact.isabeljimenez@gmail.com>
|
||||
Isaiah Grace <irgkenya4@gmail.com>
|
||||
Isao Jonas <isao.jonas@gmail.com>
|
||||
Iskander Sharipov <quasilyte@gmail.com>
|
||||
Ivan Babrou <ibobrik@gmail.com>
|
||||
@@ -805,6 +842,7 @@ Jacob Edelman <edelman.jd@gmail.com>
|
||||
Jacob Tomlinson <jacob@tom.linson.uk>
|
||||
Jacob Vallejo <jakeev@amazon.com>
|
||||
Jacob Wen <jian.w.wen@oracle.com>
|
||||
Jaime Cepeda <jcepedavillamayor@gmail.com>
|
||||
Jaivish Kothari <janonymous.codevulture@gmail.com>
|
||||
Jake Champlin <jake.champlin.27@gmail.com>
|
||||
Jake Moshenko <jake@devtable.com>
|
||||
@@ -819,12 +857,13 @@ James Kyburz <james.kyburz@gmail.com>
|
||||
James Kyle <james@jameskyle.org>
|
||||
James Lal <james@lightsofapollo.com>
|
||||
James Mills <prologic@shortcircuit.net.au>
|
||||
James Nesbitt <james.nesbitt@wunderkraut.com>
|
||||
James Nesbitt <jnesbitt@mirantis.com>
|
||||
James Nugent <james@jen20.com>
|
||||
James Turnbull <james@lovedthanlost.net>
|
||||
James Watkins-Harvey <jwatkins@progi-media.com>
|
||||
Jamie Hannaford <jamie@limetree.org>
|
||||
Jamshid Afshar <jafshar@yahoo.com>
|
||||
Jan Chren <dev.rindeal@gmail.com>
|
||||
Jan Keromnes <janx@linux.com>
|
||||
Jan Koprowski <jan.koprowski@gmail.com>
|
||||
Jan Pazdziora <jpazdziora@redhat.com>
|
||||
@@ -839,6 +878,7 @@ Jared Hocutt <jaredh@netapp.com>
|
||||
Jaroslaw Zabiello <hipertracker@gmail.com>
|
||||
jaseg <jaseg@jaseg.net>
|
||||
Jasmine Hegman <jasmine@jhegman.com>
|
||||
Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
Jason Divock <jdivock@gmail.com>
|
||||
Jason Giedymin <jasong@apache.org>
|
||||
Jason Green <Jason.Green@AverInformatics.Com>
|
||||
@@ -886,7 +926,7 @@ Jeroen Franse <jeroenfranse@gmail.com>
|
||||
Jeroen Jacobs <github@jeroenj.be>
|
||||
Jesse Dearing <jesse.dearing@gmail.com>
|
||||
Jesse Dubay <jesse@thefortytwo.net>
|
||||
Jessica Frazelle <acidburn@microsoft.com>
|
||||
Jessica Frazelle <jess@oxide.computer>
|
||||
Jezeniel Zapanta <jpzapanta22@gmail.com>
|
||||
Jhon Honce <jhonce@redhat.com>
|
||||
Ji.Zhilong <zhilongji@gmail.com>
|
||||
@@ -894,9 +934,11 @@ Jian Liao <jliao@alauda.io>
|
||||
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
|
||||
Jiang Jinyang <jjyruby@gmail.com>
|
||||
Jie Luo <luo612@zju.edu.cn>
|
||||
Jie Ma <jienius@outlook.com>
|
||||
Jihyun Hwang <jhhwang@telcoware.com>
|
||||
Jilles Oldenbeuving <ojilles@gmail.com>
|
||||
Jim Alateras <jima@comware.com.au>
|
||||
Jim Ehrismann <jim.ehrismann@docker.com>
|
||||
Jim Galasyn <jim.galasyn@docker.com>
|
||||
Jim Minter <jminter@redhat.com>
|
||||
Jim Perrin <jperrin@centos.org>
|
||||
@@ -934,7 +976,7 @@ John Feminella <jxf@jxf.me>
|
||||
John Gardiner Myers <jgmyers@proofpoint.com>
|
||||
John Gossman <johngos@microsoft.com>
|
||||
John Harris <john@johnharris.io>
|
||||
John Howard (VM) <John.Howard@microsoft.com>
|
||||
John Howard <github@lowenna.com>
|
||||
John Laswell <john.n.laswell@gmail.com>
|
||||
John Maguire <jmaguire@duosecurity.com>
|
||||
John Mulhausen <john@docker.com>
|
||||
@@ -948,6 +990,8 @@ John Willis <john.willis@docker.com>
|
||||
Jon Johnson <jonjohnson@google.com>
|
||||
Jon Surrell <jon.surrell@gmail.com>
|
||||
Jon Wedaman <jweede@gmail.com>
|
||||
Jonas Dohse <jonas@dohse.ch>
|
||||
Jonas Heinrich <Jonas@JonasHeinrich.com>
|
||||
Jonas Pfenniger <jonas@pfenniger.name>
|
||||
Jonathan A. Schweder <jonathanschweder@gmail.com>
|
||||
Jonathan A. Sternberg <jonathansternberg@gmail.com>
|
||||
@@ -997,10 +1041,13 @@ Julien Dubois <julien.dubois@gmail.com>
|
||||
Julien Kassar <github@kassisol.com>
|
||||
Julien Maitrehenry <julien.maitrehenry@me.com>
|
||||
Julien Pervillé <julien.perville@perfect-memory.com>
|
||||
Julien Pivotto <roidelapluie@inuits.eu>
|
||||
Julio Guerra <julio@sqreen.com>
|
||||
Julio Montes <imc.coder@gmail.com>
|
||||
Jun-Ru Chang <jrjang@gmail.com>
|
||||
Jussi Nummelin <jussi.nummelin@gmail.com>
|
||||
Justas Brazauskas <brazauskasjustas@gmail.com>
|
||||
Justen Martin <jmart@the-coder.com>
|
||||
Justin Cormack <justin.cormack@docker.com>
|
||||
Justin Force <justin.force@gmail.com>
|
||||
Justin Menga <justin.menga@gmail.com>
|
||||
@@ -1009,6 +1056,7 @@ Justin Simonelis <justin.p.simonelis@gmail.com>
|
||||
Justin Terry <juterry@microsoft.com>
|
||||
Justyn Temme <justyntemme@gmail.com>
|
||||
Jyrki Puttonen <jyrkiput@gmail.com>
|
||||
Jérémy Leherpeur <amenophis@leherpeur.net>
|
||||
Jérôme Petazzoni <jerome.petazzoni@docker.com>
|
||||
Jörg Thalheim <joerg@higgsboson.tk>
|
||||
K. Heller <pestophagous@gmail.com>
|
||||
@@ -1046,6 +1094,7 @@ Ken Reese <krrgithub@gmail.com>
|
||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||
Kenjiro Nakayama <nakayamakenjiro@gmail.com>
|
||||
Kent Johnson <kentoj@gmail.com>
|
||||
Kenta Tada <Kenta.Tada@sony.com>
|
||||
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
|
||||
Kevin Burke <kev@inburke.com>
|
||||
Kevin Clark <kevin.clark@gmail.com>
|
||||
@@ -1056,6 +1105,7 @@ Kevin Kern <kaiwentan@harmonycloud.cn>
|
||||
Kevin Menard <kevin@nirvdrum.com>
|
||||
Kevin Meredith <kevin.m.meredith@gmail.com>
|
||||
Kevin P. Kucharczyk <kevinkucharczyk@gmail.com>
|
||||
Kevin Parsons <kevpar@microsoft.com>
|
||||
Kevin Richardson <kevin@kevinrichardson.co>
|
||||
Kevin Shi <kshi@andrew.cmu.edu>
|
||||
Kevin Wallace <kevin@pentabarf.net>
|
||||
@@ -1146,6 +1196,7 @@ longliqiang88 <394564827@qq.com>
|
||||
Lorenz Leutgeb <lorenz.leutgeb@gmail.com>
|
||||
Lorenzo Fontana <fontanalorenz@gmail.com>
|
||||
Lotus Fenn <fenn.lotus@gmail.com>
|
||||
Louis Delossantos <ldelossa.ld@gmail.com>
|
||||
Louis Opter <kalessin@kalessin.fr>
|
||||
Luca Favatella <luca.favatella@erlang-solutions.com>
|
||||
Luca Marturana <lucamarturana@gmail.com>
|
||||
@@ -1154,9 +1205,11 @@ Luca-Bogdan Grigorescu <Luca-Bogdan Grigorescu>
|
||||
Lucas Chan <lucas-github@lucaschan.com>
|
||||
Lucas Chi <lucas@teacherspayteachers.com>
|
||||
Lucas Molas <lmolas@fundacionsadosky.org.ar>
|
||||
Lucas Silvestre <lukas.silvestre@gmail.com>
|
||||
Luciano Mores <leslau@gmail.com>
|
||||
Luis Martínez de Bartolomé Izquierdo <lmartinez@biicode.com>
|
||||
Luiz Svoboda <luizek@gmail.com>
|
||||
Lukas Heeren <lukas-heeren@hotmail.com>
|
||||
Lukas Waslowski <cr7pt0gr4ph7@gmail.com>
|
||||
lukaspustina <lukas.pustina@centerdevice.com>
|
||||
Lukasz Zajaczkowski <Lukasz.Zajaczkowski@ts.fujitsu.com>
|
||||
@@ -1256,6 +1309,7 @@ Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Mattias Jernberg <nostrad@gmail.com>
|
||||
Mauricio Garavaglia <mauricio@medallia.com>
|
||||
mauriyouth <mauriyouth@gmail.com>
|
||||
Max Harmathy <max.harmathy@web.de>
|
||||
Max Shytikov <mshytikov@gmail.com>
|
||||
Maxim Fedchyshyn <sevmax@gmail.com>
|
||||
Maxim Ivanov <ivanov.maxim@gmail.com>
|
||||
@@ -1296,6 +1350,7 @@ Michael Stapelberg <michael+gh@stapelberg.de>
|
||||
Michael Steinert <mike.steinert@gmail.com>
|
||||
Michael Thies <michaelthies78@gmail.com>
|
||||
Michael West <mwest@mdsol.com>
|
||||
Michael Zhao <michael.zhao@arm.com>
|
||||
Michal Fojtik <mfojtik@redhat.com>
|
||||
Michal Gebauer <mishak@mishak.net>
|
||||
Michal Jemala <michal.jemala@gmail.com>
|
||||
@@ -1312,6 +1367,7 @@ Miguel Morales <mimoralea@gmail.com>
|
||||
Mihai Borobocea <MihaiBorob@gmail.com>
|
||||
Mihuleacc Sergiu <mihuleac.sergiu@gmail.com>
|
||||
Mike Brown <brownwm@us.ibm.com>
|
||||
Mike Bush <mpbush@gmail.com>
|
||||
Mike Casas <mkcsas0@gmail.com>
|
||||
Mike Chelen <michael.chelen@gmail.com>
|
||||
Mike Danese <mikedanese@google.com>
|
||||
@@ -1380,6 +1436,7 @@ Neyazul Haque <nuhaque@gmail.com>
|
||||
Nghia Tran <nghia@google.com>
|
||||
Niall O'Higgins <niallo@unworkable.org>
|
||||
Nicholas E. Rabenau <nerab@gmx.at>
|
||||
Nick Adcock <nick.adcock@docker.com>
|
||||
Nick DeCoursin <n.decoursin@foodpanda.com>
|
||||
Nick Irvine <nfirvine@nfirvine.com>
|
||||
Nick Neisen <nwneisen@gmail.com>
|
||||
@@ -1403,6 +1460,7 @@ Nik Nyby <nikolas@gnu.org>
|
||||
Nikhil Chawla <chawlanikhil24@gmail.com>
|
||||
NikolaMandic <mn080202@gmail.com>
|
||||
Nikolas Garofil <nikolas.garofil@uantwerpen.be>
|
||||
Nikolay Edigaryev <edigaryev@gmail.com>
|
||||
Nikolay Milovanov <nmil@itransformers.net>
|
||||
Nirmal Mehta <nirmalkmehta@gmail.com>
|
||||
Nishant Totla <nishanttotla@gmail.com>
|
||||
@@ -1418,6 +1476,7 @@ Nuutti Kotivuori <naked@iki.fi>
|
||||
nzwsch <hi@nzwsch.com>
|
||||
O.S. Tezer <ostezer@gmail.com>
|
||||
objectified <objectified@gmail.com>
|
||||
Odin Ugedal <odin@ugedal.com>
|
||||
Oguz Bilgic <fisyonet@gmail.com>
|
||||
Oh Jinkyun <tintypemolly@gmail.com>
|
||||
Ohad Schneider <ohadschn@users.noreply.github.com>
|
||||
@@ -1428,6 +1487,7 @@ Oliver Reason <oli@overrateddev.co>
|
||||
Olivier Gambier <dmp42@users.noreply.github.com>
|
||||
Olle Jonsson <olle.jonsson@gmail.com>
|
||||
Olli Janatuinen <olli.janatuinen@gmail.com>
|
||||
Olly Pomeroy <oppomeroy@gmail.com>
|
||||
Omri Shiv <Omri.Shiv@teradata.com>
|
||||
Oriol Francès <oriolfa@gmail.com>
|
||||
Oskar Niburski <oskarniburski@gmail.com>
|
||||
@@ -1437,6 +1497,7 @@ Ovidio Mallo <ovidio.mallo@gmail.com>
|
||||
Panagiotis Moustafellos <pmoust@elastic.co>
|
||||
Paolo G. Giarrusso <p.giarrusso@gmail.com>
|
||||
Pascal <pascalgn@users.noreply.github.com>
|
||||
Pascal Bach <pascal.bach@siemens.com>
|
||||
Pascal Borreli <pascal@borreli.com>
|
||||
Pascal Hartig <phartig@rdrei.net>
|
||||
Patrick Böänziger <patrick.baenziger@bsi-software.com>
|
||||
@@ -1461,6 +1522,7 @@ Paul Nasrat <pnasrat@gmail.com>
|
||||
Paul Weaver <pauweave@cisco.com>
|
||||
Paulo Ribeiro <paigr.io@gmail.com>
|
||||
Pavel Lobashov <ShockwaveNN@gmail.com>
|
||||
Pavel Matěja <pavel@verotel.cz>
|
||||
Pavel Pletenev <cpp.create@gmail.com>
|
||||
Pavel Pospisil <pospispa@gmail.com>
|
||||
Pavel Sutyrin <pavel.sutyrin@gmail.com>
|
||||
@@ -1572,6 +1634,7 @@ Riku Voipio <riku.voipio@linaro.org>
|
||||
Riley Guerin <rileytg.dev@gmail.com>
|
||||
Ritesh H Shukla <sritesh@vmware.com>
|
||||
Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
|
||||
Rob Gulewich <rgulewich@netflix.com>
|
||||
Rob Vesse <rvesse@dotnetrdf.org>
|
||||
Robert Bachmann <rb@robertbachmann.at>
|
||||
Robert Bittle <guywithnose@gmail.com>
|
||||
@@ -1580,11 +1643,13 @@ Robert Schneider <mail@shakeme.info>
|
||||
Robert Stern <lexandro2000@gmail.com>
|
||||
Robert Terhaar <rterhaar@atlanticdynamic.com>
|
||||
Robert Wallis <smilingrob@gmail.com>
|
||||
Robert Wang <robert@arctic.tw>
|
||||
Roberto G. Hashioka <roberto.hashioka@docker.com>
|
||||
Roberto Muñoz Fernández <robertomf@gmail.com>
|
||||
Robin Naundorf <r.naundorf@fh-muenster.de>
|
||||
Robin Schneider <ypid@riseup.net>
|
||||
Robin Speekenbrink <robin@kingsquare.nl>
|
||||
Robin Thoni <robin@rthoni.com>
|
||||
robpc <rpcann@gmail.com>
|
||||
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
||||
Rodrigo Vaz <rodrigo.vaz@gmail.com>
|
||||
@@ -1599,6 +1664,7 @@ Roland Kammerer <roland.kammerer@linbit.com>
|
||||
Roland Moriz <rmoriz@users.noreply.github.com>
|
||||
Roma Sokolov <sokolov.r.v@gmail.com>
|
||||
Roman Dudin <katrmr@gmail.com>
|
||||
Roman Mazur <roman@balena.io>
|
||||
Roman Strashkin <roman.strashkin@gmail.com>
|
||||
Ron Smits <ron.smits@gmail.com>
|
||||
Ron Williams <ron.a.williams@gmail.com>
|
||||
@@ -1618,6 +1684,7 @@ Rozhnov Alexandr <nox73@ya.ru>
|
||||
Rudolph Gottesheim <r.gottesheim@loot.at>
|
||||
Rui Cao <ruicao@alauda.io>
|
||||
Rui Lopes <rgl@ruilopes.com>
|
||||
Ruilin Li <liruilin4@huawei.com>
|
||||
Runshen Zhu <runshen.zhu@gmail.com>
|
||||
Russ Magee <rmagee@gmail.com>
|
||||
Ryan Abrams <rdabrams@gmail.com>
|
||||
@@ -1656,6 +1723,7 @@ Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
||||
Sam Neirinck <sam@samneirinck.com>
|
||||
Sam Reis <sreis@atlassian.com>
|
||||
Sam Rijs <srijs@airpost.net>
|
||||
Sam Whited <sam@samwhited.com>
|
||||
Sambuddha Basu <sambuddhabasu1@gmail.com>
|
||||
Sami Wagiaalla <swagiaal@redhat.com>
|
||||
Samuel Andaya <samuel@andaya.net>
|
||||
@@ -1670,6 +1738,7 @@ sapphiredev <se.imas.kr@gmail.com>
|
||||
Sargun Dhillon <sargun@netflix.com>
|
||||
Sascha Andres <sascha.andres@outlook.com>
|
||||
Sascha Grunert <sgrunert@suse.com>
|
||||
SataQiu <qiushida@beyondcent.com>
|
||||
Satnam Singh <satnam@raintown.org>
|
||||
Satoshi Amemiya <satoshi_amemiya@voyagegroup.com>
|
||||
Satoshi Tagomori <tagomoris@gmail.com>
|
||||
@@ -1718,6 +1787,7 @@ Shijun Qin <qinshijun16@mails.ucas.ac.cn>
|
||||
Shishir Mahajan <shishir.mahajan@redhat.com>
|
||||
Shoubhik Bose <sbose78@gmail.com>
|
||||
Shourya Sarcar <shourya.sarcar@gmail.com>
|
||||
Shu-Wai Chow <shu-wai.chow@seattlechildrens.org>
|
||||
shuai-z <zs.broccoli@gmail.com>
|
||||
Shukui Yang <yangshukui@huawei.com>
|
||||
Shuwei Hao <haosw@cn.ibm.com>
|
||||
@@ -1728,6 +1798,7 @@ Silas Sewell <silas@sewell.org>
|
||||
Silvan Jegen <s.jegen@gmail.com>
|
||||
Simão Reis <smnrsti@gmail.com>
|
||||
Simei He <hesimei@zju.edu.cn>
|
||||
Simon Barendse <simon.barendse@gmail.com>
|
||||
Simon Eskildsen <sirup@sirupsen.com>
|
||||
Simon Ferquel <simon.ferquel@docker.com>
|
||||
Simon Leinen <simon.leinen@gmail.com>
|
||||
@@ -1736,6 +1807,7 @@ Simon Taranto <simon.taranto@gmail.com>
|
||||
Simon Vikstrom <pullreq@devsn.se>
|
||||
Sindhu S <sindhus@live.in>
|
||||
Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
|
||||
skanehira <sho19921005@gmail.com>
|
||||
Solganik Alexander <solganik@gmail.com>
|
||||
Solomon Hykes <solomon@docker.com>
|
||||
Song Gao <song@gao.io>
|
||||
@@ -1747,18 +1819,21 @@ Sridatta Thatipamala <sthatipamala@gmail.com>
|
||||
Sridhar Ratnakumar <sridharr@activestate.com>
|
||||
Srini Brahmaroutu <srbrahma@us.ibm.com>
|
||||
Srinivasan Srivatsan <srinivasan.srivatsan@hpe.com>
|
||||
Staf Wagemakers <staf@wagemakers.be>
|
||||
Stanislav Bondarenko <stanislav.bondarenko@gmail.com>
|
||||
Stanislav Levin <slev@altlinux.org>
|
||||
Steeve Morin <steeve.morin@gmail.com>
|
||||
Stefan Berger <stefanb@linux.vnet.ibm.com>
|
||||
Stefan J. Wernli <swernli@microsoft.com>
|
||||
Stefan Praszalowicz <stefan@greplin.com>
|
||||
Stefan S. <tronicum@user.github.com>
|
||||
Stefan Scherer <scherer_stefan@icloud.com>
|
||||
Stefan Scherer <stefan.scherer@docker.com>
|
||||
Stefan Staudenmeyer <doerte@instana.com>
|
||||
Stefan Weil <sw@weilnetz.de>
|
||||
Stephan Spindler <shutefan@gmail.com>
|
||||
Stephen Benjamin <stephen@redhat.com>
|
||||
Stephen Crosby <stevecrozz@gmail.com>
|
||||
Stephen Day <stephen.day@docker.com>
|
||||
Stephen Day <stevvooe@gmail.com>
|
||||
Stephen Drake <stephen@xenolith.net>
|
||||
Stephen Rust <srust@blockbridge.com>
|
||||
Steve Desmond <steve@vtsv.ca>
|
||||
@@ -1773,10 +1848,12 @@ Steven Iveson <sjiveson@outlook.com>
|
||||
Steven Merrill <steven.merrill@gmail.com>
|
||||
Steven Richards <steven@axiomzen.co>
|
||||
Steven Taylor <steven.taylor@me.com>
|
||||
Stig Larsson <stig@larsson.dev>
|
||||
Subhajit Ghosh <isubuz.g@gmail.com>
|
||||
Sujith Haridasan <sujith.h@gmail.com>
|
||||
Sun Gengze <690388648@qq.com>
|
||||
Sun Jianbo <wonderflow.sun@gmail.com>
|
||||
Sune Keller <sune.keller@gmail.com>
|
||||
Sunny Gogoi <indiasuny000@gmail.com>
|
||||
Suryakumar Sudar <surya.trunks@gmail.com>
|
||||
Sven Dowideit <SvenDowideit@home.org.au>
|
||||
@@ -1827,6 +1904,8 @@ Tianyi Wang <capkurmagati@gmail.com>
|
||||
Tibor Vass <teabee89@gmail.com>
|
||||
Tiffany Jernigan <tiffany.f.j@gmail.com>
|
||||
Tiffany Low <tiffany@box.com>
|
||||
Till Wegmüller <toasterson@gmail.com>
|
||||
Tim <elatllat@gmail.com>
|
||||
Tim Bart <tim@fewagainstmany.com>
|
||||
Tim Bosse <taim@bosboot.org>
|
||||
Tim Dettrick <t.dettrick@uq.edu.au>
|
||||
@@ -1878,7 +1957,7 @@ Tony Miller <mcfiredrill@gmail.com>
|
||||
toogley <toogley@mailbox.org>
|
||||
Torstein Husebø <torstein@huseboe.net>
|
||||
Tõnis Tiigi <tonistiigi@gmail.com>
|
||||
tpng <benny.tpng@gmail.com>
|
||||
Trace Andreason <tandreason@gmail.com>
|
||||
tracylihui <793912329@qq.com>
|
||||
Trapier Marshall <trapier.marshall@docker.com>
|
||||
Travis Cline <travis.cline@gmail.com>
|
||||
@@ -1901,6 +1980,7 @@ Utz Bacher <utz.bacher@de.ibm.com>
|
||||
vagrant <vagrant@ubuntu-14.04-amd64-vbox>
|
||||
Vaidas Jablonskis <jablonskis@gmail.com>
|
||||
vanderliang <lansheng@meili-inc.com>
|
||||
Velko Ivanov <vivanov@deeperplane.com>
|
||||
Veres Lajos <vlajos@gmail.com>
|
||||
Victor Algaze <valgaze@gmail.com>
|
||||
Victor Coisne <victor.coisne@dotcloud.com>
|
||||
@@ -1912,11 +1992,13 @@ Victor Palma <palma.victor@gmail.com>
|
||||
Victor Vieux <victor.vieux@docker.com>
|
||||
Victoria Bialas <victoria.bialas@docker.com>
|
||||
Vijaya Kumar K <vijayak@caviumnetworks.com>
|
||||
Vikram bir Singh <vsingh@mirantis.com>
|
||||
Viktor Stanchev <me@viktorstanchev.com>
|
||||
Viktor Vojnovski <viktor.vojnovski@amadeus.com>
|
||||
VinayRaghavanKS <raghavan.vinay@gmail.com>
|
||||
Vincent Batts <vbatts@redhat.com>
|
||||
Vincent Bernat <Vincent.Bernat@exoscale.ch>
|
||||
Vincent Boulineau <vincent.boulineau@datadoghq.com>
|
||||
Vincent Demeester <vincent.demeester@docker.com>
|
||||
Vincent Giersch <vincent.giersch@ovh.net>
|
||||
Vincent Mayers <vincent.mayers@inbloom.org>
|
||||
@@ -1947,6 +2029,8 @@ Wang Long <long.wanglong@huawei.com>
|
||||
Wang Ping <present.wp@icloud.com>
|
||||
Wang Xing <hzwangxing@corp.netease.com>
|
||||
Wang Yuexiao <wang.yuexiao@zte.com.cn>
|
||||
Wang Yumu <37442693@qq.com>
|
||||
wanghuaiqing <wanghuaiqing@loongson.cn>
|
||||
Ward Vandewege <ward@jhvc.com>
|
||||
WarheadsSE <max@warheads.net>
|
||||
Wassim Dhif <wassimdhif@gmail.com>
|
||||
@@ -1963,12 +2047,14 @@ Wen Cheng Ma <wenchma@cn.ibm.com>
|
||||
Wendel Fleming <wfleming@usc.edu>
|
||||
Wenjun Tang <tangwj2@lenovo.com>
|
||||
Wenkai Yin <yinw@vmware.com>
|
||||
wenlxie <wenlxie@ebay.com>
|
||||
Wentao Zhang <zhangwentao234@huawei.com>
|
||||
Wenxuan Zhao <viz@linux.com>
|
||||
Wenyu You <21551128@zju.edu.cn>
|
||||
Wenzhi Liang <wenzhi.liang@gmail.com>
|
||||
Wes Morgan <cap10morgan@gmail.com>
|
||||
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
|
||||
Wiktor Kwapisiewicz <wiktor@metacode.biz>
|
||||
Will Dietz <w@wdtz.org>
|
||||
Will Rouesnel <w.rouesnel@gmail.com>
|
||||
Will Weaver <monkey@buildingbananas.com>
|
||||
@@ -1979,6 +2065,8 @@ William Hubbs <w.d.hubbs@gmail.com>
|
||||
William Martin <wmartin@pivotal.io>
|
||||
William Riancho <wr.wllm@gmail.com>
|
||||
William Thurston <thurstw@amazon.com>
|
||||
Wilson Júnior <wilsonpjunior@gmail.com>
|
||||
Wing-Kam Wong <wingkwong.code@gmail.com>
|
||||
WiseTrem <shepelyov.g@gmail.com>
|
||||
Wolfgang Powisch <powo@powo.priv.at>
|
||||
Wonjun Kim <wonjun.kim@navercorp.com>
|
||||
@@ -1988,6 +2076,7 @@ Xianglin Gao <xlgao@zju.edu.cn>
|
||||
Xianlu Bird <xianlubird@gmail.com>
|
||||
Xiao YongBiao <xyb4638@gmail.com>
|
||||
XiaoBing Jiang <s7v7nislands@gmail.com>
|
||||
Xiaodong Liu <liuxiaodong@loongson.cn>
|
||||
Xiaodong Zhang <a4012017@sina.com>
|
||||
Xiaoxi He <xxhe@alauda.io>
|
||||
Xiaoxu Chen <chenxiaoxu14@otcaix.iscas.ac.cn>
|
||||
@@ -1996,6 +2085,7 @@ xichengliudui <1693291525@qq.com>
|
||||
xiekeyang <xiekeyang@huawei.com>
|
||||
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
|
||||
Xinbo Weng <xihuanbo_0521@zju.edu.cn>
|
||||
Xinfeng Liu <xinfeng.liu@gmail.com>
|
||||
Xinzi Zhou <imdreamrunner@gmail.com>
|
||||
Xiuming Chen <cc@cxm.cc>
|
||||
Xuecong Liao <satorulogic@gmail.com>
|
||||
@@ -2010,6 +2100,7 @@ Yang Pengfei <yangpengfei4@huawei.com>
|
||||
yangchenliang <yangchenliang@huawei.com>
|
||||
Yanqiang Miao <miao.yanqiang@zte.com.cn>
|
||||
Yao Zaiyong <yaozaiyong@hotmail.com>
|
||||
Yash Murty <yashmurty@gmail.com>
|
||||
Yassine Tijani <yasstij11@gmail.com>
|
||||
Yasunori Mahata <nori@mahata.net>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
@@ -2024,6 +2115,7 @@ Yongxin Li <yxli@alauda.io>
|
||||
Yongzhi Pan <panyongzhi@gmail.com>
|
||||
Yosef Fertel <yfertel@gmail.com>
|
||||
You-Sheng Yang (楊有勝) <vicamo@gmail.com>
|
||||
youcai <omegacoleman@gmail.com>
|
||||
Youcef YEKHLEF <yyekhlef@gmail.com>
|
||||
Yu Changchun <yuchangchun1@huawei.com>
|
||||
Yu Chengxia <yuchengxia@huawei.com>
|
||||
@@ -2055,11 +2147,13 @@ Zhenan Ye <21551168@zju.edu.cn>
|
||||
zhenghenghuo <zhenghenghuo@zju.edu.cn>
|
||||
Zhenhai Gao <gaozh1988@live.com>
|
||||
Zhenkun Bi <bi.zhenkun@zte.com.cn>
|
||||
zhipengzuo <zuozhipeng@baidu.com>
|
||||
Zhou Hao <zhouhao@cn.fujitsu.com>
|
||||
Zhoulin Xie <zhoulin.xie@daocloud.io>
|
||||
Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
|
||||
Zhu Kunjia <zhu.kunjia@zte.com.cn>
|
||||
Zhuoyun Wei <wzyboy@wzyboy.org>
|
||||
Ziheng Liu <lzhfromustc@gmail.com>
|
||||
Zilin Du <zilin.du@gmail.com>
|
||||
zimbatm <zimbatm@zimbatm.com>
|
||||
Ziming Dong <bnudzm@foxmail.com>
|
||||
@@ -2068,12 +2162,13 @@ zmarouf <zeid.marouf@gmail.com>
|
||||
Zoltan Tombol <zoltan.tombol@gmail.com>
|
||||
Zou Yu <zouyu7@huawei.com>
|
||||
zqh <zqhxuyuan@gmail.com>
|
||||
Zuhayr Elahi <elahi.zuhayr@gmail.com>
|
||||
Zuhayr Elahi <zuhayr.elahi@docker.com>
|
||||
Zunayed Ali <zunayed@gmail.com>
|
||||
Álex González <agonzalezro@gmail.com>
|
||||
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
|
||||
Átila Camurça Alves <camurca.home@gmail.com>
|
||||
尹吉峰 <jifeng.yin@gmail.com>
|
||||
屈骏 <qujun@tiduyun.com>
|
||||
徐俊杰 <paco.xu@daocloud.io>
|
||||
慕陶 <jihui.xjh@alibaba-inc.com>
|
||||
搏通 <yufeng.pyf@alibaba-inc.com>
|
||||
|
||||
84
vendor/github.com/docker/docker/pkg/term/deprecated.go
generated
vendored
Normal file
84
vendor/github.com/docker/docker/pkg/term/deprecated.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Package term provides structures and helper functions to work with
|
||||
// terminal (state, sizes).
|
||||
//
|
||||
// Deprecated: use github.com/moby/term instead
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
// EscapeError is special error which returned by a TTY proxy reader's Read()
|
||||
// method in case its detach escape sequence is read.
|
||||
// Deprecated: use github.com/moby/term.EscapeError
|
||||
type EscapeError = term.EscapeError
|
||||
|
||||
// State represents the state of the terminal.
|
||||
// Deprecated: use github.com/moby/term.State
|
||||
type State = term.State
|
||||
|
||||
// Winsize represents the size of the terminal window.
|
||||
// Deprecated: use github.com/moby/term.Winsize
|
||||
type Winsize = term.Winsize
|
||||
|
||||
var (
|
||||
// ASCII list the possible supported ASCII key sequence
|
||||
ASCII = term.ASCII
|
||||
|
||||
// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code.
|
||||
// Deprecated: use github.com/moby/term.ToBytes
|
||||
ToBytes = term.ToBytes
|
||||
|
||||
// StdStreams returns the standard streams (stdin, stdout, stderr).
|
||||
// Deprecated: use github.com/moby/term.StdStreams
|
||||
StdStreams = term.StdStreams
|
||||
|
||||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
|
||||
// Deprecated: use github.com/moby/term.GetFdInfo
|
||||
GetFdInfo = term.GetFdInfo
|
||||
|
||||
// GetWinsize returns the window size based on the specified file descriptor.
|
||||
// Deprecated: use github.com/moby/term.GetWinsize
|
||||
GetWinsize = term.GetWinsize
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
// Deprecated: use github.com/moby/term.IsTerminal
|
||||
IsTerminal = term.IsTerminal
|
||||
|
||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||
// to a previous state.
|
||||
// Deprecated: use github.com/moby/term.RestoreTerminal
|
||||
RestoreTerminal = term.RestoreTerminal
|
||||
|
||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||
// Deprecated: use github.com/moby/term.SaveState
|
||||
SaveState = term.SaveState
|
||||
|
||||
// DisableEcho applies the specified state to the terminal connected to the file
|
||||
// descriptor, with echo disabled.
|
||||
// Deprecated: use github.com/moby/term.DisableEcho
|
||||
DisableEcho = term.DisableEcho
|
||||
|
||||
// SetRawTerminal puts the terminal connected to the given file descriptor into
|
||||
// raw mode and returns the previous state. On UNIX, this puts both the input
|
||||
// and output into raw mode. On Windows, it only puts the input into raw mode.
|
||||
// Deprecated: use github.com/moby/term.SetRawTerminal
|
||||
SetRawTerminal = term.SetRawTerminal
|
||||
|
||||
// SetRawTerminalOutput puts the output of terminal connected to the given file
|
||||
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
|
||||
// state. On Windows, it disables LF -> CRLF translation.
|
||||
// Deprecated: use github.com/moby/term.SetRawTerminalOutput
|
||||
SetRawTerminalOutput = term.SetRawTerminalOutput
|
||||
|
||||
// MakeRaw puts the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be restored.
|
||||
// Deprecated: use github.com/moby/term.MakeRaw
|
||||
MakeRaw = term.MakeRaw
|
||||
|
||||
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
|
||||
// and detects when the specified escape keys are read, in which case the Read
|
||||
// method will return an error of type EscapeError.
|
||||
// Deprecated: use github.com/moby/term.NewEscapeProxy
|
||||
NewEscapeProxy = term.NewEscapeProxy
|
||||
)
|
||||
21
vendor/github.com/docker/docker/pkg/term/deprecated_unix.go
generated
vendored
Normal file
21
vendor/github.com/docker/docker/pkg/term/deprecated_unix.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
// Termios is the Unix API for terminal I/O.
|
||||
// Deprecated: use github.com/moby/term.Termios
|
||||
type Termios = term.Termios
|
||||
|
||||
var (
|
||||
// ErrInvalidState is returned if the state of the terminal is invalid.
|
||||
ErrInvalidState = term.ErrInvalidState
|
||||
|
||||
// SetWinsize tries to set the specified window size for the specified file descriptor.
|
||||
// Deprecated: use github.com/moby/term.GetWinsize
|
||||
SetWinsize = term.SetWinsize
|
||||
)
|
||||
78
vendor/github.com/docker/docker/pkg/term/proxy.go
generated
vendored
78
vendor/github.com/docker/docker/pkg/term/proxy.go
generated
vendored
@@ -1,78 +0,0 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// EscapeError is special error which returned by a TTY proxy reader's Read()
|
||||
// method in case its detach escape sequence is read.
|
||||
type EscapeError struct{}
|
||||
|
||||
func (EscapeError) Error() string {
|
||||
return "read escape sequence"
|
||||
}
|
||||
|
||||
// escapeProxy is used only for attaches with a TTY. It is used to proxy
|
||||
// stdin keypresses from the underlying reader and look for the passed in
|
||||
// escape key sequence to signal a detach.
|
||||
type escapeProxy struct {
|
||||
escapeKeys []byte
|
||||
escapeKeyPos int
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
|
||||
// and detects when the specified escape keys are read, in which case the Read
|
||||
// method will return an error of type EscapeError.
|
||||
func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader {
|
||||
return &escapeProxy{
|
||||
escapeKeys: escapeKeys,
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *escapeProxy) Read(buf []byte) (int, error) {
|
||||
nr, err := r.r.Read(buf)
|
||||
|
||||
if len(r.escapeKeys) == 0 {
|
||||
return nr, err
|
||||
}
|
||||
|
||||
preserve := func() {
|
||||
// this preserves the original key presses in the passed in buffer
|
||||
nr += r.escapeKeyPos
|
||||
preserve := make([]byte, 0, r.escapeKeyPos+len(buf))
|
||||
preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...)
|
||||
preserve = append(preserve, buf...)
|
||||
r.escapeKeyPos = 0
|
||||
copy(buf[0:nr], preserve)
|
||||
}
|
||||
|
||||
if nr != 1 || err != nil {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, err
|
||||
}
|
||||
|
||||
if buf[0] != r.escapeKeys[r.escapeKeyPos] {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, nil
|
||||
}
|
||||
|
||||
if r.escapeKeyPos == len(r.escapeKeys)-1 {
|
||||
return 0, EscapeError{}
|
||||
}
|
||||
|
||||
// Looks like we've got an escape key, but we need to match again on the next
|
||||
// read.
|
||||
// Store the current escape key we found so we can look for the next one on
|
||||
// the next read.
|
||||
// Since this is an escape key, make sure we don't let the caller read it
|
||||
// If later on we find that this is not the escape sequence, we'll add the
|
||||
// keys back
|
||||
r.escapeKeyPos++
|
||||
return nr - r.escapeKeyPos, nil
|
||||
}
|
||||
20
vendor/github.com/docker/docker/pkg/term/tc.go
generated
vendored
20
vendor/github.com/docker/docker/pkg/term/tc.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func tcget(fd uintptr, p *Termios) syscall.Errno {
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(p)))
|
||||
return err
|
||||
}
|
||||
|
||||
func tcset(fd uintptr, p *Termios) syscall.Errno {
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(p)))
|
||||
return err
|
||||
}
|
||||
42
vendor/github.com/docker/docker/pkg/term/termios_bsd.go
generated
vendored
42
vendor/github.com/docker/docker/pkg/term/termios_bsd.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
// +build darwin freebsd openbsd netbsd
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TIOCGETA
|
||||
setTermios = unix.TIOCSETA
|
||||
)
|
||||
|
||||
// Termios is the Unix API for terminal I/O.
|
||||
type Termios unix.Termios
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd uintptr) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
newState.Oflag &^= unix.OPOST
|
||||
newState.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
|
||||
newState.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
newState.Cflag |= unix.CS8
|
||||
newState.Cc[unix.VMIN] = 1
|
||||
newState.Cc[unix.VTIME] = 0
|
||||
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
||||
33
vendor/github.com/docker/docker/pkg/term/windows/windows.go
generated
vendored
33
vendor/github.com/docker/docker/pkg/term/windows/windows.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
|
||||
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
|
||||
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/Azure/go-ansiterm"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var logger *logrus.Logger
|
||||
var initOnce sync.Once
|
||||
|
||||
func initLogger() {
|
||||
initOnce.Do(func() {
|
||||
logFile := ioutil.Discard
|
||||
|
||||
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
|
||||
logFile, _ = os.Create("ansiReaderWriter.log")
|
||||
}
|
||||
|
||||
logger = &logrus.Logger{
|
||||
Out: logFile,
|
||||
Formatter: new(logrus.TextFormatter),
|
||||
Level: logrus.DebugLevel,
|
||||
}
|
||||
})
|
||||
}
|
||||
20
vendor/github.com/fatih/color/LICENSE.md
generated
vendored
Normal file
20
vendor/github.com/fatih/color/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Fatih Arslan
|
||||
|
||||
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.
|
||||
178
vendor/github.com/fatih/color/README.md
generated
vendored
Normal file
178
vendor/github.com/fatih/color/README.md
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
# color [](https://github.com/fatih/color/actions) [](https://pkg.go.dev/github.com/fatih/color)
|
||||
|
||||
Color lets you use colorized outputs in terms of [ANSI Escape
|
||||
Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
|
||||
has support for Windows too! The API can be used in several ways, pick one that
|
||||
suits you.
|
||||
|
||||

|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
go get github.com/fatih/color
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Standard colors
|
||||
|
||||
```go
|
||||
// Print with default helper functions
|
||||
color.Cyan("Prints text in cyan.")
|
||||
|
||||
// A newline will be appended automatically
|
||||
color.Blue("Prints %s in blue.", "text")
|
||||
|
||||
// These are using the default foreground colors
|
||||
color.Red("We have red")
|
||||
color.Magenta("And many others ..")
|
||||
|
||||
```
|
||||
|
||||
### Mix and reuse colors
|
||||
|
||||
```go
|
||||
// Create a new color object
|
||||
c := color.New(color.FgCyan).Add(color.Underline)
|
||||
c.Println("Prints cyan text with an underline.")
|
||||
|
||||
// Or just add them to New()
|
||||
d := color.New(color.FgCyan, color.Bold)
|
||||
d.Printf("This prints bold cyan %s\n", "too!.")
|
||||
|
||||
// Mix up foreground and background colors, create new mixes!
|
||||
red := color.New(color.FgRed)
|
||||
|
||||
boldRed := red.Add(color.Bold)
|
||||
boldRed.Println("This will print text in bold red.")
|
||||
|
||||
whiteBackground := red.Add(color.BgWhite)
|
||||
whiteBackground.Println("Red text with white background.")
|
||||
```
|
||||
|
||||
### Use your own output (io.Writer)
|
||||
|
||||
```go
|
||||
// Use your own io.Writer output
|
||||
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
|
||||
|
||||
blue := color.New(color.FgBlue)
|
||||
blue.Fprint(writer, "This will print text in blue.")
|
||||
```
|
||||
|
||||
### Custom print functions (PrintFunc)
|
||||
|
||||
```go
|
||||
// Create a custom print function for convenience
|
||||
red := color.New(color.FgRed).PrintfFunc()
|
||||
red("Warning")
|
||||
red("Error: %s", err)
|
||||
|
||||
// Mix up multiple attributes
|
||||
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
|
||||
notice("Don't forget this...")
|
||||
```
|
||||
|
||||
### Custom fprint functions (FprintFunc)
|
||||
|
||||
```go
|
||||
blue := color.New(color.FgBlue).FprintfFunc()
|
||||
blue(myWriter, "important notice: %s", stars)
|
||||
|
||||
// Mix up with multiple attributes
|
||||
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
|
||||
success(myWriter, "Don't forget this...")
|
||||
```
|
||||
|
||||
### Insert into noncolor strings (SprintFunc)
|
||||
|
||||
```go
|
||||
// Create SprintXxx functions to mix strings with other non-colorized strings:
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
red := color.New(color.FgRed).SprintFunc()
|
||||
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
|
||||
|
||||
info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
|
||||
fmt.Printf("This %s rocks!\n", info("package"))
|
||||
|
||||
// Use helper functions
|
||||
fmt.Println("This", color.RedString("warning"), "should be not neglected.")
|
||||
fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.")
|
||||
|
||||
// Windows supported too! Just don't forget to change the output to color.Output
|
||||
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
|
||||
```
|
||||
|
||||
### Plug into existing code
|
||||
|
||||
```go
|
||||
// Use handy standard colors
|
||||
color.Set(color.FgYellow)
|
||||
|
||||
fmt.Println("Existing text will now be in yellow")
|
||||
fmt.Printf("This one %s\n", "too")
|
||||
|
||||
color.Unset() // Don't forget to unset
|
||||
|
||||
// You can mix up parameters
|
||||
color.Set(color.FgMagenta, color.Bold)
|
||||
defer color.Unset() // Use it in your function
|
||||
|
||||
fmt.Println("All text will now be bold magenta.")
|
||||
```
|
||||
|
||||
### Disable/Enable color
|
||||
|
||||
There might be a case where you want to explicitly disable/enable color output. the
|
||||
`go-isatty` package will automatically disable color output for non-tty output streams
|
||||
(for example if the output were piped directly to `less`).
|
||||
|
||||
The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
|
||||
variable is set (regardless of its value).
|
||||
|
||||
`Color` has support to disable/enable colors programatically both globally and
|
||||
for single color definitions. For example suppose you have a CLI app and a
|
||||
`--no-color` bool flag. You can easily disable the color output with:
|
||||
|
||||
```go
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
|
||||
if *flagNoColor {
|
||||
color.NoColor = true // disables colorized output
|
||||
}
|
||||
```
|
||||
|
||||
It also has support for single color definitions (local). You can
|
||||
disable/enable color output on the fly:
|
||||
|
||||
```go
|
||||
c := color.New(color.FgCyan)
|
||||
c.Println("Prints cyan text")
|
||||
|
||||
c.DisableColor()
|
||||
c.Println("This is printed without any color")
|
||||
|
||||
c.EnableColor()
|
||||
c.Println("This prints again cyan...")
|
||||
```
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams.
|
||||
|
||||
## Todo
|
||||
|
||||
* Save/Return previous values
|
||||
* Evaluate fmt.Formatter interface
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
* [Fatih Arslan](https://github.com/fatih)
|
||||
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details
|
||||
618
vendor/github.com/fatih/color/color.go
generated
vendored
Normal file
618
vendor/github.com/fatih/color/color.go
generated
vendored
Normal file
@@ -0,0 +1,618 @@
|
||||
package color
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
var (
|
||||
// NoColor defines if the output is colorized or not. It's dynamically set to
|
||||
// false or true based on the stdout's file descriptor referring to a terminal
|
||||
// or not. It's also set to true if the NO_COLOR environment variable is
|
||||
// set (regardless of its value). This is a global option and affects all
|
||||
// colors. For more control over each color block use the methods
|
||||
// DisableColor() individually.
|
||||
NoColor = noColorExists() || os.Getenv("TERM") == "dumb" ||
|
||||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
|
||||
|
||||
// Output defines the standard output of the print functions. By default
|
||||
// os.Stdout is used.
|
||||
Output = colorable.NewColorableStdout()
|
||||
|
||||
// Error defines a color supporting writer for os.Stderr.
|
||||
Error = colorable.NewColorableStderr()
|
||||
|
||||
// colorsCache is used to reduce the count of created Color objects and
|
||||
// allows to reuse already created objects with required Attribute.
|
||||
colorsCache = make(map[Attribute]*Color)
|
||||
colorsCacheMu sync.Mutex // protects colorsCache
|
||||
)
|
||||
|
||||
// noColorExists returns true if the environment variable NO_COLOR exists.
|
||||
func noColorExists() bool {
|
||||
_, exists := os.LookupEnv("NO_COLOR")
|
||||
return exists
|
||||
}
|
||||
|
||||
// Color defines a custom color object which is defined by SGR parameters.
|
||||
type Color struct {
|
||||
params []Attribute
|
||||
noColor *bool
|
||||
}
|
||||
|
||||
// Attribute defines a single SGR Code
|
||||
type Attribute int
|
||||
|
||||
const escape = "\x1b"
|
||||
|
||||
// Base attributes
|
||||
const (
|
||||
Reset Attribute = iota
|
||||
Bold
|
||||
Faint
|
||||
Italic
|
||||
Underline
|
||||
BlinkSlow
|
||||
BlinkRapid
|
||||
ReverseVideo
|
||||
Concealed
|
||||
CrossedOut
|
||||
)
|
||||
|
||||
// Foreground text colors
|
||||
const (
|
||||
FgBlack Attribute = iota + 30
|
||||
FgRed
|
||||
FgGreen
|
||||
FgYellow
|
||||
FgBlue
|
||||
FgMagenta
|
||||
FgCyan
|
||||
FgWhite
|
||||
)
|
||||
|
||||
// Foreground Hi-Intensity text colors
|
||||
const (
|
||||
FgHiBlack Attribute = iota + 90
|
||||
FgHiRed
|
||||
FgHiGreen
|
||||
FgHiYellow
|
||||
FgHiBlue
|
||||
FgHiMagenta
|
||||
FgHiCyan
|
||||
FgHiWhite
|
||||
)
|
||||
|
||||
// Background text colors
|
||||
const (
|
||||
BgBlack Attribute = iota + 40
|
||||
BgRed
|
||||
BgGreen
|
||||
BgYellow
|
||||
BgBlue
|
||||
BgMagenta
|
||||
BgCyan
|
||||
BgWhite
|
||||
)
|
||||
|
||||
// Background Hi-Intensity text colors
|
||||
const (
|
||||
BgHiBlack Attribute = iota + 100
|
||||
BgHiRed
|
||||
BgHiGreen
|
||||
BgHiYellow
|
||||
BgHiBlue
|
||||
BgHiMagenta
|
||||
BgHiCyan
|
||||
BgHiWhite
|
||||
)
|
||||
|
||||
// New returns a newly created color object.
|
||||
func New(value ...Attribute) *Color {
|
||||
c := &Color{
|
||||
params: make([]Attribute, 0),
|
||||
}
|
||||
|
||||
if noColorExists() {
|
||||
c.noColor = boolPtr(true)
|
||||
}
|
||||
|
||||
c.Add(value...)
|
||||
return c
|
||||
}
|
||||
|
||||
// Set sets the given parameters immediately. It will change the color of
|
||||
// output with the given SGR parameters until color.Unset() is called.
|
||||
func Set(p ...Attribute) *Color {
|
||||
c := New(p...)
|
||||
c.Set()
|
||||
return c
|
||||
}
|
||||
|
||||
// Unset resets all escape attributes and clears the output. Usually should
|
||||
// be called after Set().
|
||||
func Unset() {
|
||||
if NoColor {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(Output, "%s[%dm", escape, Reset)
|
||||
}
|
||||
|
||||
// Set sets the SGR sequence.
|
||||
func (c *Color) Set() *Color {
|
||||
if c.isNoColorSet() {
|
||||
return c
|
||||
}
|
||||
|
||||
fmt.Fprintf(Output, c.format())
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Color) unset() {
|
||||
if c.isNoColorSet() {
|
||||
return
|
||||
}
|
||||
|
||||
Unset()
|
||||
}
|
||||
|
||||
func (c *Color) setWriter(w io.Writer) *Color {
|
||||
if c.isNoColorSet() {
|
||||
return c
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, c.format())
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Color) unsetWriter(w io.Writer) {
|
||||
if c.isNoColorSet() {
|
||||
return
|
||||
}
|
||||
|
||||
if NoColor {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s[%dm", escape, Reset)
|
||||
}
|
||||
|
||||
// Add is used to chain SGR parameters. Use as many as parameters to combine
|
||||
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
|
||||
func (c *Color) Add(value ...Attribute) *Color {
|
||||
c.params = append(c.params, value...)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Color) prepend(value Attribute) {
|
||||
c.params = append(c.params, 0)
|
||||
copy(c.params[1:], c.params[0:])
|
||||
c.params[0] = value
|
||||
}
|
||||
|
||||
// Fprint formats using the default formats for its operands and writes to w.
|
||||
// Spaces are added between operands when neither is a string.
|
||||
// It returns the number of bytes written and any write error encountered.
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
|
||||
return fmt.Fprint(w, a...)
|
||||
}
|
||||
|
||||
// Print formats using the default formats for its operands and writes to
|
||||
// standard output. Spaces are added between operands when neither is a
|
||||
// string. It returns the number of bytes written and any write error
|
||||
// encountered. This is the standard fmt.Print() method wrapped with the given
|
||||
// color.
|
||||
func (c *Color) Print(a ...interface{}) (n int, err error) {
|
||||
c.Set()
|
||||
defer c.unset()
|
||||
|
||||
return fmt.Fprint(Output, a...)
|
||||
}
|
||||
|
||||
// Fprintf formats according to a format specifier and writes to w.
|
||||
// It returns the number of bytes written and any write error encountered.
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
|
||||
return fmt.Fprintf(w, format, a...)
|
||||
}
|
||||
|
||||
// Printf formats according to a format specifier and writes to standard output.
|
||||
// It returns the number of bytes written and any write error encountered.
|
||||
// This is the standard fmt.Printf() method wrapped with the given color.
|
||||
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
|
||||
c.Set()
|
||||
defer c.unset()
|
||||
|
||||
return fmt.Fprintf(Output, format, a...)
|
||||
}
|
||||
|
||||
// Fprintln formats using the default formats for its operands and writes to w.
|
||||
// Spaces are always added between operands and a newline is appended.
|
||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
|
||||
// type *os.File.
|
||||
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
c.setWriter(w)
|
||||
defer c.unsetWriter(w)
|
||||
|
||||
return fmt.Fprintln(w, a...)
|
||||
}
|
||||
|
||||
// Println formats using the default formats for its operands and writes to
|
||||
// standard output. Spaces are always added between operands and a newline is
|
||||
// appended. It returns the number of bytes written and any write error
|
||||
// encountered. This is the standard fmt.Print() method wrapped with the given
|
||||
// color.
|
||||
func (c *Color) Println(a ...interface{}) (n int, err error) {
|
||||
c.Set()
|
||||
defer c.unset()
|
||||
|
||||
return fmt.Fprintln(Output, a...)
|
||||
}
|
||||
|
||||
// Sprint is just like Print, but returns a string instead of printing it.
|
||||
func (c *Color) Sprint(a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Sprintln is just like Println, but returns a string instead of printing it.
|
||||
func (c *Color) Sprintln(a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprintln(a...))
|
||||
}
|
||||
|
||||
// Sprintf is just like Printf, but returns a string instead of printing it.
|
||||
func (c *Color) Sprintf(format string, a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// FprintFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Fprint().
|
||||
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
|
||||
return func(w io.Writer, a ...interface{}) {
|
||||
c.Fprint(w, a...)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Print().
|
||||
func (c *Color) PrintFunc() func(a ...interface{}) {
|
||||
return func(a ...interface{}) {
|
||||
c.Print(a...)
|
||||
}
|
||||
}
|
||||
|
||||
// FprintfFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Fprintf().
|
||||
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
|
||||
return func(w io.Writer, format string, a ...interface{}) {
|
||||
c.Fprintf(w, format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintfFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Printf().
|
||||
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
|
||||
return func(format string, a ...interface{}) {
|
||||
c.Printf(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
// FprintlnFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Fprintln().
|
||||
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
|
||||
return func(w io.Writer, a ...interface{}) {
|
||||
c.Fprintln(w, a...)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintlnFunc returns a new function that prints the passed arguments as
|
||||
// colorized with color.Println().
|
||||
func (c *Color) PrintlnFunc() func(a ...interface{}) {
|
||||
return func(a ...interface{}) {
|
||||
c.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
// SprintFunc returns a new function that returns colorized strings for the
|
||||
// given arguments with fmt.Sprint(). Useful to put into or mix into other
|
||||
// string. Windows users should use this in conjunction with color.Output, example:
|
||||
//
|
||||
// put := New(FgYellow).SprintFunc()
|
||||
// fmt.Fprintf(color.Output, "This is a %s", put("warning"))
|
||||
func (c *Color) SprintFunc() func(a ...interface{}) string {
|
||||
return func(a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprint(a...))
|
||||
}
|
||||
}
|
||||
|
||||
// SprintfFunc returns a new function that returns colorized strings for the
|
||||
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
|
||||
// string. Windows users should use this in conjunction with color.Output.
|
||||
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
|
||||
return func(format string, a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprintf(format, a...))
|
||||
}
|
||||
}
|
||||
|
||||
// SprintlnFunc returns a new function that returns colorized strings for the
|
||||
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
|
||||
// string. Windows users should use this in conjunction with color.Output.
|
||||
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
|
||||
return func(a ...interface{}) string {
|
||||
return c.wrap(fmt.Sprintln(a...))
|
||||
}
|
||||
}
|
||||
|
||||
// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
|
||||
// an example output might be: "1;36" -> bold cyan
|
||||
func (c *Color) sequence() string {
|
||||
format := make([]string, len(c.params))
|
||||
for i, v := range c.params {
|
||||
format[i] = strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
return strings.Join(format, ";")
|
||||
}
|
||||
|
||||
// wrap wraps the s string with the colors attributes. The string is ready to
|
||||
// be printed.
|
||||
func (c *Color) wrap(s string) string {
|
||||
if c.isNoColorSet() {
|
||||
return s
|
||||
}
|
||||
|
||||
return c.format() + s + c.unformat()
|
||||
}
|
||||
|
||||
func (c *Color) format() string {
|
||||
return fmt.Sprintf("%s[%sm", escape, c.sequence())
|
||||
}
|
||||
|
||||
func (c *Color) unformat() string {
|
||||
return fmt.Sprintf("%s[%dm", escape, Reset)
|
||||
}
|
||||
|
||||
// DisableColor disables the color output. Useful to not change any existing
|
||||
// code and still being able to output. Can be used for flags like
|
||||
// "--no-color". To enable back use EnableColor() method.
|
||||
func (c *Color) DisableColor() {
|
||||
c.noColor = boolPtr(true)
|
||||
}
|
||||
|
||||
// EnableColor enables the color output. Use it in conjunction with
|
||||
// DisableColor(). Otherwise this method has no side effects.
|
||||
func (c *Color) EnableColor() {
|
||||
c.noColor = boolPtr(false)
|
||||
}
|
||||
|
||||
func (c *Color) isNoColorSet() bool {
|
||||
// check first if we have user set action
|
||||
if c.noColor != nil {
|
||||
return *c.noColor
|
||||
}
|
||||
|
||||
// if not return the global option, which is disabled by default
|
||||
return NoColor
|
||||
}
|
||||
|
||||
// Equals returns a boolean value indicating whether two colors are equal.
|
||||
func (c *Color) Equals(c2 *Color) bool {
|
||||
if len(c.params) != len(c2.params) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, attr := range c.params {
|
||||
if !c2.attrExists(attr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Color) attrExists(a Attribute) bool {
|
||||
for _, attr := range c.params {
|
||||
if attr == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func boolPtr(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
func getCachedColor(p Attribute) *Color {
|
||||
colorsCacheMu.Lock()
|
||||
defer colorsCacheMu.Unlock()
|
||||
|
||||
c, ok := colorsCache[p]
|
||||
if !ok {
|
||||
c = New(p)
|
||||
colorsCache[p] = c
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func colorPrint(format string, p Attribute, a ...interface{}) {
|
||||
c := getCachedColor(p)
|
||||
|
||||
if !strings.HasSuffix(format, "\n") {
|
||||
format += "\n"
|
||||
}
|
||||
|
||||
if len(a) == 0 {
|
||||
c.Print(format)
|
||||
} else {
|
||||
c.Printf(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func colorString(format string, p Attribute, a ...interface{}) string {
|
||||
c := getCachedColor(p)
|
||||
|
||||
if len(a) == 0 {
|
||||
return c.SprintFunc()(format)
|
||||
}
|
||||
|
||||
return c.SprintfFunc()(format, a...)
|
||||
}
|
||||
|
||||
// Black is a convenient helper function to print with black foreground. A
|
||||
// newline is appended to format by default.
|
||||
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
|
||||
|
||||
// Red is a convenient helper function to print with red foreground. A
|
||||
// newline is appended to format by default.
|
||||
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
|
||||
|
||||
// Green is a convenient helper function to print with green foreground. A
|
||||
// newline is appended to format by default.
|
||||
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
|
||||
|
||||
// Yellow is a convenient helper function to print with yellow foreground.
|
||||
// A newline is appended to format by default.
|
||||
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
|
||||
|
||||
// Blue is a convenient helper function to print with blue foreground. A
|
||||
// newline is appended to format by default.
|
||||
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
|
||||
|
||||
// Magenta is a convenient helper function to print with magenta foreground.
|
||||
// A newline is appended to format by default.
|
||||
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
|
||||
|
||||
// Cyan is a convenient helper function to print with cyan foreground. A
|
||||
// newline is appended to format by default.
|
||||
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
|
||||
|
||||
// White is a convenient helper function to print with white foreground. A
|
||||
// newline is appended to format by default.
|
||||
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
|
||||
|
||||
// BlackString is a convenient helper function to return a string with black
|
||||
// foreground.
|
||||
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
|
||||
|
||||
// RedString is a convenient helper function to return a string with red
|
||||
// foreground.
|
||||
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
|
||||
|
||||
// GreenString is a convenient helper function to return a string with green
|
||||
// foreground.
|
||||
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
|
||||
|
||||
// YellowString is a convenient helper function to return a string with yellow
|
||||
// foreground.
|
||||
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
|
||||
|
||||
// BlueString is a convenient helper function to return a string with blue
|
||||
// foreground.
|
||||
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
|
||||
|
||||
// MagentaString is a convenient helper function to return a string with magenta
|
||||
// foreground.
|
||||
func MagentaString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgMagenta, a...)
|
||||
}
|
||||
|
||||
// CyanString is a convenient helper function to return a string with cyan
|
||||
// foreground.
|
||||
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
|
||||
|
||||
// WhiteString is a convenient helper function to return a string with white
|
||||
// foreground.
|
||||
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
|
||||
|
||||
// HiBlack is a convenient helper function to print with hi-intensity black foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
|
||||
|
||||
// HiRed is a convenient helper function to print with hi-intensity red foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
|
||||
|
||||
// HiGreen is a convenient helper function to print with hi-intensity green foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
|
||||
|
||||
// HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
|
||||
// A newline is appended to format by default.
|
||||
func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
|
||||
|
||||
// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
|
||||
|
||||
// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
|
||||
// A newline is appended to format by default.
|
||||
func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
|
||||
|
||||
// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
|
||||
|
||||
// HiWhite is a convenient helper function to print with hi-intensity white foreground. A
|
||||
// newline is appended to format by default.
|
||||
func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
|
||||
|
||||
// HiBlackString is a convenient helper function to return a string with hi-intensity black
|
||||
// foreground.
|
||||
func HiBlackString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgHiBlack, a...)
|
||||
}
|
||||
|
||||
// HiRedString is a convenient helper function to return a string with hi-intensity red
|
||||
// foreground.
|
||||
func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
|
||||
|
||||
// HiGreenString is a convenient helper function to return a string with hi-intensity green
|
||||
// foreground.
|
||||
func HiGreenString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgHiGreen, a...)
|
||||
}
|
||||
|
||||
// HiYellowString is a convenient helper function to return a string with hi-intensity yellow
|
||||
// foreground.
|
||||
func HiYellowString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgHiYellow, a...)
|
||||
}
|
||||
|
||||
// HiBlueString is a convenient helper function to return a string with hi-intensity blue
|
||||
// foreground.
|
||||
func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
|
||||
|
||||
// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
|
||||
// foreground.
|
||||
func HiMagentaString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgHiMagenta, a...)
|
||||
}
|
||||
|
||||
// HiCyanString is a convenient helper function to return a string with hi-intensity cyan
|
||||
// foreground.
|
||||
func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
|
||||
|
||||
// HiWhiteString is a convenient helper function to return a string with hi-intensity white
|
||||
// foreground.
|
||||
func HiWhiteString(format string, a ...interface{}) string {
|
||||
return colorString(format, FgHiWhite, a...)
|
||||
}
|
||||
135
vendor/github.com/fatih/color/doc.go
generated
vendored
Normal file
135
vendor/github.com/fatih/color/doc.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
Package color is an ANSI color package to output colorized or SGR defined
|
||||
output to the standard output. The API can be used in several way, pick one
|
||||
that suits you.
|
||||
|
||||
Use simple and default helper functions with predefined foreground colors:
|
||||
|
||||
color.Cyan("Prints text in cyan.")
|
||||
|
||||
// a newline will be appended automatically
|
||||
color.Blue("Prints %s in blue.", "text")
|
||||
|
||||
// More default foreground colors..
|
||||
color.Red("We have red")
|
||||
color.Yellow("Yellow color too!")
|
||||
color.Magenta("And many others ..")
|
||||
|
||||
// Hi-intensity colors
|
||||
color.HiGreen("Bright green color.")
|
||||
color.HiBlack("Bright black means gray..")
|
||||
color.HiWhite("Shiny white color!")
|
||||
|
||||
However there are times where custom color mixes are required. Below are some
|
||||
examples to create custom color objects and use the print functions of each
|
||||
separate color object.
|
||||
|
||||
// Create a new color object
|
||||
c := color.New(color.FgCyan).Add(color.Underline)
|
||||
c.Println("Prints cyan text with an underline.")
|
||||
|
||||
// Or just add them to New()
|
||||
d := color.New(color.FgCyan, color.Bold)
|
||||
d.Printf("This prints bold cyan %s\n", "too!.")
|
||||
|
||||
|
||||
// Mix up foreground and background colors, create new mixes!
|
||||
red := color.New(color.FgRed)
|
||||
|
||||
boldRed := red.Add(color.Bold)
|
||||
boldRed.Println("This will print text in bold red.")
|
||||
|
||||
whiteBackground := red.Add(color.BgWhite)
|
||||
whiteBackground.Println("Red text with White background.")
|
||||
|
||||
// Use your own io.Writer output
|
||||
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
|
||||
|
||||
blue := color.New(color.FgBlue)
|
||||
blue.Fprint(myWriter, "This will print text in blue.")
|
||||
|
||||
You can create PrintXxx functions to simplify even more:
|
||||
|
||||
// Create a custom print function for convenient
|
||||
red := color.New(color.FgRed).PrintfFunc()
|
||||
red("warning")
|
||||
red("error: %s", err)
|
||||
|
||||
// Mix up multiple attributes
|
||||
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
|
||||
notice("don't forget this...")
|
||||
|
||||
You can also FprintXxx functions to pass your own io.Writer:
|
||||
|
||||
blue := color.New(FgBlue).FprintfFunc()
|
||||
blue(myWriter, "important notice: %s", stars)
|
||||
|
||||
// Mix up with multiple attributes
|
||||
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
|
||||
success(myWriter, don't forget this...")
|
||||
|
||||
|
||||
Or create SprintXxx functions to mix strings with other non-colorized strings:
|
||||
|
||||
yellow := New(FgYellow).SprintFunc()
|
||||
red := New(FgRed).SprintFunc()
|
||||
|
||||
fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
|
||||
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Printf("this %s rocks!\n", info("package"))
|
||||
|
||||
Windows support is enabled by default. All Print functions work as intended.
|
||||
However only for color.SprintXXX functions, user should use fmt.FprintXXX and
|
||||
set the output to color.Output:
|
||||
|
||||
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
|
||||
|
||||
info := New(FgWhite, BgGreen).SprintFunc()
|
||||
fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
|
||||
|
||||
Using with existing code is possible. Just use the Set() method to set the
|
||||
standard output to the given parameters. That way a rewrite of an existing
|
||||
code is not required.
|
||||
|
||||
// Use handy standard colors.
|
||||
color.Set(color.FgYellow)
|
||||
|
||||
fmt.Println("Existing text will be now in Yellow")
|
||||
fmt.Printf("This one %s\n", "too")
|
||||
|
||||
color.Unset() // don't forget to unset
|
||||
|
||||
// You can mix up parameters
|
||||
color.Set(color.FgMagenta, color.Bold)
|
||||
defer color.Unset() // use it in your function
|
||||
|
||||
fmt.Println("All text will be now bold magenta.")
|
||||
|
||||
There might be a case where you want to disable color output (for example to
|
||||
pipe the standard output of your app to somewhere else). `Color` has support to
|
||||
disable colors both globally and for single color definition. For example
|
||||
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
|
||||
the color output with:
|
||||
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
|
||||
if *flagNoColor {
|
||||
color.NoColor = true // disables colorized output
|
||||
}
|
||||
|
||||
You can also disable the color by setting the NO_COLOR environment variable to any value.
|
||||
|
||||
It also has support for single color definitions (local). You can
|
||||
disable/enable color output on the fly:
|
||||
|
||||
c := color.New(color.FgCyan)
|
||||
c.Println("Prints cyan text")
|
||||
|
||||
c.DisableColor()
|
||||
c.Println("This is printed without any color")
|
||||
|
||||
c.EnableColor()
|
||||
c.Println("This prints again cyan...")
|
||||
*/
|
||||
package color
|
||||
42
vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
generated
vendored
42
vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
generated
vendored
@@ -1,42 +0,0 @@
|
||||
# Windows Terminal Sequences
|
||||
|
||||
This library allow for enabling Windows terminal color support for Go.
|
||||
|
||||
See [Console Virtual Terminal Sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for details.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
sequences "github.com/konsorten/go-windows-terminal-sequences"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sequences.EnableVirtualTerminalProcessing(syscall.Stdout, true)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Authors
|
||||
|
||||
The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de).
|
||||
|
||||
We thank all the authors who provided code to this library:
|
||||
|
||||
* Felix Kollmann
|
||||
* Nicolas Perraut
|
||||
* @dirty49374
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2018 marvin + konsorten GmbH (open-source@konsorten.de)
|
||||
|
||||
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.
|
||||
35
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
generated
vendored
35
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package sequences
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32Dll *syscall.LazyDLL = syscall.NewLazyDLL("Kernel32.dll")
|
||||
setConsoleMode *syscall.LazyProc = kernel32Dll.NewProc("SetConsoleMode")
|
||||
)
|
||||
|
||||
func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
|
||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING uint32 = 0x4
|
||||
|
||||
var mode uint32
|
||||
err := syscall.GetConsoleMode(syscall.Stdout, &mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if enable {
|
||||
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
} else {
|
||||
mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
}
|
||||
|
||||
ret, _, err := setConsoleMode.Call(uintptr(stream), uintptr(mode))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
11
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go
generated
vendored
11
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go
generated
vendored
@@ -1,11 +0,0 @@
|
||||
// +build linux darwin
|
||||
|
||||
package sequences
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func EnableVirtualTerminalProcessing(stream uintptr, enable bool) error {
|
||||
return fmt.Errorf("windows only package")
|
||||
}
|
||||
21
vendor/github.com/mattn/go-colorable/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mattn/go-colorable/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
||||
|
||||
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.
|
||||
48
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
Normal file
48
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# go-colorable
|
||||
|
||||
[](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest)
|
||||
[](https://codecov.io/gh/mattn/go-colorable)
|
||||
[](http://godoc.org/github.com/mattn/go-colorable)
|
||||
[](https://goreportcard.com/report/mattn/go-colorable)
|
||||
|
||||
Colorable writer for windows.
|
||||
|
||||
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
|
||||
This package is possible to handle escape sequence for ansi color on windows.
|
||||
|
||||
## Too Bad!
|
||||
|
||||

|
||||
|
||||
|
||||
## So Good!
|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
|
||||
logrus.SetOutput(colorable.NewColorableStdout())
|
||||
|
||||
logrus.Info("succeeded")
|
||||
logrus.Warn("not correct")
|
||||
logrus.Error("something error")
|
||||
logrus.Fatal("panic")
|
||||
```
|
||||
|
||||
You can compile above code on non-windows OSs.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get github.com/mattn/go-colorable
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
MIT
|
||||
|
||||
# Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
||||
38
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
Normal file
38
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
_ "github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// NewColorable returns new instance of Writer which handles escape sequence.
|
||||
func NewColorable(file *os.File) io.Writer {
|
||||
if file == nil {
|
||||
panic("nil passed instead of *os.File to NewColorable()")
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
|
||||
func NewColorableStdout() io.Writer {
|
||||
return os.Stdout
|
||||
}
|
||||
|
||||
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
|
||||
func NewColorableStderr() io.Writer {
|
||||
return os.Stderr
|
||||
}
|
||||
|
||||
// EnableColorsStdout enable colors if possible.
|
||||
func EnableColorsStdout(enabled *bool) func() {
|
||||
if enabled != nil {
|
||||
*enabled = true
|
||||
}
|
||||
return func() {}
|
||||
}
|
||||
38
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
Normal file
38
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
//go:build !windows && !appengine
|
||||
// +build !windows,!appengine
|
||||
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
_ "github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// NewColorable returns new instance of Writer which handles escape sequence.
|
||||
func NewColorable(file *os.File) io.Writer {
|
||||
if file == nil {
|
||||
panic("nil passed instead of *os.File to NewColorable()")
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
|
||||
func NewColorableStdout() io.Writer {
|
||||
return os.Stdout
|
||||
}
|
||||
|
||||
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
|
||||
func NewColorableStderr() io.Writer {
|
||||
return os.Stderr
|
||||
}
|
||||
|
||||
// EnableColorsStdout enable colors if possible.
|
||||
func EnableColorsStdout(enabled *bool) func() {
|
||||
if enabled != nil {
|
||||
*enabled = true
|
||||
}
|
||||
return func() {}
|
||||
}
|
||||
1047
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
Normal file
1047
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
for d in $(go list ./... | grep -v vendor); do
|
||||
go test -race -coverprofile=profile.out -covermode=atomic "$d"
|
||||
if [ -f profile.out ]; then
|
||||
cat profile.out >> coverage.txt
|
||||
rm profile.out
|
||||
fi
|
||||
done
|
||||
57
vendor/github.com/mattn/go-colorable/noncolorable.go
generated
vendored
Normal file
57
vendor/github.com/mattn/go-colorable/noncolorable.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package colorable
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// NonColorable holds writer but removes escape sequence.
|
||||
type NonColorable struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
// NewNonColorable returns new instance of Writer which removes escape sequence from Writer.
|
||||
func NewNonColorable(w io.Writer) io.Writer {
|
||||
return &NonColorable{out: w}
|
||||
}
|
||||
|
||||
// Write writes data on console
|
||||
func (w *NonColorable) Write(data []byte) (n int, err error) {
|
||||
er := bytes.NewReader(data)
|
||||
var plaintext bytes.Buffer
|
||||
loop:
|
||||
for {
|
||||
c1, err := er.ReadByte()
|
||||
if err != nil {
|
||||
plaintext.WriteTo(w.out)
|
||||
break loop
|
||||
}
|
||||
if c1 != 0x1b {
|
||||
plaintext.WriteByte(c1)
|
||||
continue
|
||||
}
|
||||
_, err = plaintext.WriteTo(w.out)
|
||||
if err != nil {
|
||||
break loop
|
||||
}
|
||||
c2, err := er.ReadByte()
|
||||
if err != nil {
|
||||
break loop
|
||||
}
|
||||
if c2 != 0x5b {
|
||||
continue
|
||||
}
|
||||
|
||||
for {
|
||||
c, err := er.ReadByte()
|
||||
if err != nil {
|
||||
break loop
|
||||
}
|
||||
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len(data), nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
(The MIT License)
|
||||
Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
|
||||
|
||||
Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
|
||||
MIT License (Expat)
|
||||
|
||||
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:
|
||||
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.
|
||||
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.
|
||||
50
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
Normal file
50
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# go-isatty
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-isatty)
|
||||
[](https://codecov.io/gh/mattn/go-isatty)
|
||||
[](https://coveralls.io/github/mattn/go-isatty?branch=master)
|
||||
[](https://goreportcard.com/report/mattn/go-isatty)
|
||||
|
||||
isatty for golang
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mattn/go-isatty"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Terminal")
|
||||
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Cygwin/MSYS2 Terminal")
|
||||
} else {
|
||||
fmt.Println("Is Not Terminal")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get github.com/mattn/go-isatty
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
||||
|
||||
## Thanks
|
||||
|
||||
* k-takata: base idea for IsCygwinTerminal
|
||||
|
||||
https://github.com/k-takata/go-iscygpty
|
||||
2
vendor/github.com/mattn/go-isatty/doc.go
generated
vendored
Normal file
2
vendor/github.com/mattn/go-isatty/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package isatty implements interface to isatty
|
||||
package isatty
|
||||
12
vendor/github.com/mattn/go-isatty/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-isatty/go.test.sh
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
for d in $(go list ./... | grep -v vendor); do
|
||||
go test -race -coverprofile=profile.out -covermode=atomic "$d"
|
||||
if [ -f profile.out ]; then
|
||||
cat profile.out >> coverage.txt
|
||||
rm profile.out
|
||||
fi
|
||||
done
|
||||
19
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
Normal file
19
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine
|
||||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
_, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
16
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
Normal file
16
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build appengine || js || nacl || wasm
|
||||
// +build appengine js nacl wasm
|
||||
|
||||
package isatty
|
||||
|
||||
// IsTerminal returns true if the file descriptor is terminal which
|
||||
// is always false on js and appengine classic which is a sandboxed PaaS.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
23
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
Normal file
23
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
//go:build plan9
|
||||
// +build plan9
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
path, err := syscall.Fd2path(int(fd))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return path == "/dev/cons" || path == "/mnt/term/dev/cons"
|
||||
}
|
||||
|
||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
21
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
Normal file
21
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build solaris && !appengine
|
||||
// +build solaris,!appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
_, err := unix.IoctlGetTermio(int(fd), unix.TCGETA)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
19
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
Normal file
19
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
//go:build (linux || aix || zos) && !appengine
|
||||
// +build linux aix zos
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
125
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
Normal file
125
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
//go:build windows && !appengine
|
||||
// +build windows,!appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
objectNameInfo uintptr = 1
|
||||
fileNameInfo = 2
|
||||
fileTypePipe = 3
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
ntdll = syscall.NewLazyDLL("ntdll.dll")
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
|
||||
procGetFileType = kernel32.NewProc("GetFileType")
|
||||
procNtQueryObject = ntdll.NewProc("NtQueryObject")
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Check if GetFileInformationByHandleEx is available.
|
||||
if procGetFileInformationByHandleEx.Find() != nil {
|
||||
procGetFileInformationByHandleEx = nil
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
}
|
||||
|
||||
// Check pipe name is used for cygwin/msys2 pty.
|
||||
// Cygwin/MSYS2 PTY has a name like:
|
||||
// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
|
||||
func isCygwinPipeName(name string) bool {
|
||||
token := strings.Split(name, "-")
|
||||
if len(token) < 5 {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[0] != `\msys` &&
|
||||
token[0] != `\cygwin` &&
|
||||
token[0] != `\Device\NamedPipe\msys` &&
|
||||
token[0] != `\Device\NamedPipe\cygwin` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[1] == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(token[2], "pty") {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[3] != `from` && token[3] != `to` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[4] != "master" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
|
||||
// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion
|
||||
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
|
||||
// Windows vista to 10
|
||||
// see https://stackoverflow.com/a/18792477 for details
|
||||
func getFileNameByHandle(fd uintptr) (string, error) {
|
||||
if procNtQueryObject == nil {
|
||||
return "", errors.New("ntdll.dll: NtQueryObject not supported")
|
||||
}
|
||||
|
||||
var buf [4 + syscall.MAX_PATH]uint16
|
||||
var result int
|
||||
r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5,
|
||||
fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0)
|
||||
if r != 0 {
|
||||
return "", e
|
||||
}
|
||||
return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
if procGetFileInformationByHandleEx == nil {
|
||||
name, err := getFileNameByHandle(fd)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return isCygwinPipeName(name)
|
||||
}
|
||||
|
||||
// Cygwin/msys's pty is a pipe.
|
||||
ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
|
||||
if ft != fileTypePipe || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var buf [2 + syscall.MAX_PATH]uint16
|
||||
r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
|
||||
4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
|
||||
uintptr(len(buf)*2), 0, 0)
|
||||
if r == 0 || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
l := *(*uint32)(unsafe.Pointer(&buf))
|
||||
return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
|
||||
}
|
||||
16
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal file
16
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.13.x
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
- go get -t -v ./...
|
||||
|
||||
script:
|
||||
- go generate
|
||||
- git diff --cached --exit-code
|
||||
- ./go.test.sh
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
||||
|
||||
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.
|
||||
27
vendor/github.com/mattn/go-runewidth/README.md
generated
vendored
Normal file
27
vendor/github.com/mattn/go-runewidth/README.md
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
go-runewidth
|
||||
============
|
||||
|
||||
[](https://travis-ci.org/mattn/go-runewidth)
|
||||
[](https://codecov.io/gh/mattn/go-runewidth)
|
||||
[](http://godoc.org/github.com/mattn/go-runewidth)
|
||||
[](https://goreportcard.com/report/github.com/mattn/go-runewidth)
|
||||
|
||||
Provides functions to get fixed width of the character or string.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```go
|
||||
runewidth.StringWidth("つのだ☆HIRO") == 12
|
||||
```
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
Yasuhiro Matsumoto
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
under the MIT License: http://mattn.mit-license.org/2013
|
||||
12
vendor/github.com/mattn/go-runewidth/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-runewidth/go.test.sh
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
for d in $(go list ./... | grep -v vendor); do
|
||||
go test -race -coverprofile=profile.out -covermode=atomic "$d"
|
||||
if [ -f profile.out ]; then
|
||||
cat profile.out >> coverage.txt
|
||||
rm profile.out
|
||||
fi
|
||||
done
|
||||
273
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
Normal file
273
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
//go:generate go run script/generate.go
|
||||
|
||||
var (
|
||||
// EastAsianWidth will be set true if the current locale is CJK
|
||||
EastAsianWidth bool
|
||||
|
||||
// StrictEmojiNeutral should be set false if handle broken fonts
|
||||
StrictEmojiNeutral bool = true
|
||||
|
||||
// DefaultCondition is a condition in current locale
|
||||
DefaultCondition = &Condition{
|
||||
EastAsianWidth: false,
|
||||
StrictEmojiNeutral: true,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
handleEnv()
|
||||
}
|
||||
|
||||
func handleEnv() {
|
||||
env := os.Getenv("RUNEWIDTH_EASTASIAN")
|
||||
if env == "" {
|
||||
EastAsianWidth = IsEastAsian()
|
||||
} else {
|
||||
EastAsianWidth = env == "1"
|
||||
}
|
||||
// update DefaultCondition
|
||||
DefaultCondition.EastAsianWidth = EastAsianWidth
|
||||
}
|
||||
|
||||
type interval struct {
|
||||
first rune
|
||||
last rune
|
||||
}
|
||||
|
||||
type table []interval
|
||||
|
||||
func inTables(r rune, ts ...table) bool {
|
||||
for _, t := range ts {
|
||||
if inTable(r, t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func inTable(r rune, t table) bool {
|
||||
if r < t[0].first {
|
||||
return false
|
||||
}
|
||||
|
||||
bot := 0
|
||||
top := len(t) - 1
|
||||
for top >= bot {
|
||||
mid := (bot + top) >> 1
|
||||
|
||||
switch {
|
||||
case t[mid].last < r:
|
||||
bot = mid + 1
|
||||
case t[mid].first > r:
|
||||
top = mid - 1
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var private = table{
|
||||
{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
|
||||
}
|
||||
|
||||
var nonprint = table{
|
||||
{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
|
||||
{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
|
||||
{0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
|
||||
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
|
||||
}
|
||||
|
||||
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
|
||||
type Condition struct {
|
||||
EastAsianWidth bool
|
||||
StrictEmojiNeutral bool
|
||||
}
|
||||
|
||||
// NewCondition return new instance of Condition which is current locale.
|
||||
func NewCondition() *Condition {
|
||||
return &Condition{
|
||||
EastAsianWidth: EastAsianWidth,
|
||||
StrictEmojiNeutral: StrictEmojiNeutral,
|
||||
}
|
||||
}
|
||||
|
||||
// RuneWidth returns the number of cells in r.
|
||||
// See http://www.unicode.org/reports/tr11/
|
||||
func (c *Condition) RuneWidth(r rune) int {
|
||||
// optimized version, verified by TestRuneWidthChecksums()
|
||||
if !c.EastAsianWidth {
|
||||
switch {
|
||||
case r < 0x20 || r > 0x10FFFF:
|
||||
return 0
|
||||
case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
|
||||
return 0
|
||||
case r < 0x300:
|
||||
return 1
|
||||
case inTable(r, narrow):
|
||||
return 1
|
||||
case inTables(r, nonprint, combining):
|
||||
return 0
|
||||
case inTable(r, doublewidth):
|
||||
return 2
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining):
|
||||
return 0
|
||||
case inTable(r, narrow):
|
||||
return 1
|
||||
case inTables(r, ambiguous, doublewidth):
|
||||
return 2
|
||||
case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
|
||||
return 2
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StringWidth return width as you can see
|
||||
func (c *Condition) StringWidth(s string) (width int) {
|
||||
g := uniseg.NewGraphemes(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Runes() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // Our best guess at this point is to use the width of the first non-zero-width rune.
|
||||
}
|
||||
}
|
||||
width += chWidth
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Truncate return string truncated with w cells
|
||||
func (c *Condition) Truncate(s string, w int, tail string) string {
|
||||
if c.StringWidth(s) <= w {
|
||||
return s
|
||||
}
|
||||
w -= c.StringWidth(tail)
|
||||
var width int
|
||||
pos := len(s)
|
||||
g := uniseg.NewGraphemes(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Runes() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // See StringWidth() for details.
|
||||
}
|
||||
}
|
||||
if width+chWidth > w {
|
||||
pos, _ = g.Positions()
|
||||
break
|
||||
}
|
||||
width += chWidth
|
||||
}
|
||||
return s[:pos] + tail
|
||||
}
|
||||
|
||||
// Wrap return string wrapped with w cells
|
||||
func (c *Condition) Wrap(s string, w int) string {
|
||||
width := 0
|
||||
out := ""
|
||||
for _, r := range []rune(s) {
|
||||
cw := c.RuneWidth(r)
|
||||
if r == '\n' {
|
||||
out += string(r)
|
||||
width = 0
|
||||
continue
|
||||
} else if width+cw > w {
|
||||
out += "\n"
|
||||
width = 0
|
||||
out += string(r)
|
||||
width += cw
|
||||
continue
|
||||
}
|
||||
out += string(r)
|
||||
width += cw
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// FillLeft return string filled in left by spaces in w cells
|
||||
func (c *Condition) FillLeft(s string, w int) string {
|
||||
width := c.StringWidth(s)
|
||||
count := w - width
|
||||
if count > 0 {
|
||||
b := make([]byte, count)
|
||||
for i := range b {
|
||||
b[i] = ' '
|
||||
}
|
||||
return string(b) + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FillRight return string filled in left by spaces in w cells
|
||||
func (c *Condition) FillRight(s string, w int) string {
|
||||
width := c.StringWidth(s)
|
||||
count := w - width
|
||||
if count > 0 {
|
||||
b := make([]byte, count)
|
||||
for i := range b {
|
||||
b[i] = ' '
|
||||
}
|
||||
return s + string(b)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// RuneWidth returns the number of cells in r.
|
||||
// See http://www.unicode.org/reports/tr11/
|
||||
func RuneWidth(r rune) int {
|
||||
return DefaultCondition.RuneWidth(r)
|
||||
}
|
||||
|
||||
// IsAmbiguousWidth returns whether is ambiguous width or not.
|
||||
func IsAmbiguousWidth(r rune) bool {
|
||||
return inTables(r, private, ambiguous)
|
||||
}
|
||||
|
||||
// IsNeutralWidth returns whether is neutral width or not.
|
||||
func IsNeutralWidth(r rune) bool {
|
||||
return inTable(r, neutral)
|
||||
}
|
||||
|
||||
// StringWidth return width as you can see
|
||||
func StringWidth(s string) (width int) {
|
||||
return DefaultCondition.StringWidth(s)
|
||||
}
|
||||
|
||||
// Truncate return string truncated with w cells
|
||||
func Truncate(s string, w int, tail string) string {
|
||||
return DefaultCondition.Truncate(s, w, tail)
|
||||
}
|
||||
|
||||
// Wrap return string wrapped with w cells
|
||||
func Wrap(s string, w int) string {
|
||||
return DefaultCondition.Wrap(s, w)
|
||||
}
|
||||
|
||||
// FillLeft return string filled in left by spaces in w cells
|
||||
func FillLeft(s string, w int) string {
|
||||
return DefaultCondition.FillLeft(s, w)
|
||||
}
|
||||
|
||||
// FillRight return string filled in left by spaces in w cells
|
||||
func FillRight(s string, w int) string {
|
||||
return DefaultCondition.FillRight(s, w)
|
||||
}
|
||||
8
vendor/github.com/mattn/go-runewidth/runewidth_appengine.go
generated
vendored
Normal file
8
vendor/github.com/mattn/go-runewidth/runewidth_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// +build appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
return false
|
||||
}
|
||||
9
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
9
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build js
|
||||
// +build !appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
func IsEastAsian() bool {
|
||||
// TODO: Implement this for the web. Detect east asian in a compatible way, and return true.
|
||||
return false
|
||||
}
|
||||
82
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
82
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// +build !windows
|
||||
// +build !js
|
||||
// +build !appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
|
||||
|
||||
var mblenTable = map[string]int{
|
||||
"utf-8": 6,
|
||||
"utf8": 6,
|
||||
"jis": 8,
|
||||
"eucjp": 3,
|
||||
"euckr": 2,
|
||||
"euccn": 2,
|
||||
"sjis": 2,
|
||||
"cp932": 2,
|
||||
"cp51932": 2,
|
||||
"cp936": 2,
|
||||
"cp949": 2,
|
||||
"cp950": 2,
|
||||
"big5": 2,
|
||||
"gbk": 2,
|
||||
"gb2312": 2,
|
||||
}
|
||||
|
||||
func isEastAsian(locale string) bool {
|
||||
charset := strings.ToLower(locale)
|
||||
r := reLoc.FindStringSubmatch(locale)
|
||||
if len(r) == 2 {
|
||||
charset = strings.ToLower(r[1])
|
||||
}
|
||||
|
||||
if strings.HasSuffix(charset, "@cjk_narrow") {
|
||||
return false
|
||||
}
|
||||
|
||||
for pos, b := range []byte(charset) {
|
||||
if b == '@' {
|
||||
charset = charset[:pos]
|
||||
break
|
||||
}
|
||||
}
|
||||
max := 1
|
||||
if m, ok := mblenTable[charset]; ok {
|
||||
max = m
|
||||
}
|
||||
if max > 1 && (charset[0] != 'u' ||
|
||||
strings.HasPrefix(locale, "ja") ||
|
||||
strings.HasPrefix(locale, "ko") ||
|
||||
strings.HasPrefix(locale, "zh")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
locale := os.Getenv("LC_ALL")
|
||||
if locale == "" {
|
||||
locale = os.Getenv("LC_CTYPE")
|
||||
}
|
||||
if locale == "" {
|
||||
locale = os.Getenv("LANG")
|
||||
}
|
||||
|
||||
// ignore C locale
|
||||
if locale == "POSIX" || locale == "C" {
|
||||
return false
|
||||
}
|
||||
if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') {
|
||||
return false
|
||||
}
|
||||
|
||||
return isEastAsian(locale)
|
||||
}
|
||||
439
vendor/github.com/mattn/go-runewidth/runewidth_table.go
generated
vendored
Normal file
439
vendor/github.com/mattn/go-runewidth/runewidth_table.go
generated
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
// Code generated by script/generate.go. DO NOT EDIT.
|
||||
|
||||
package runewidth
|
||||
|
||||
var combining = table{
|
||||
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
|
||||
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0D00, 0x0D01},
|
||||
{0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1AC0},
|
||||
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DF9}, {0x1DFB, 0x1DFF},
|
||||
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
|
||||
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
|
||||
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
|
||||
{0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A},
|
||||
{0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x11300, 0x11301},
|
||||
{0x1133B, 0x1133C}, {0x11366, 0x1136C}, {0x11370, 0x11374},
|
||||
{0x16AF0, 0x16AF4}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172},
|
||||
{0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
|
||||
{0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
|
||||
{0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A},
|
||||
{0x1E8D0, 0x1E8D6},
|
||||
}
|
||||
|
||||
var doublewidth = table{
|
||||
{0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A},
|
||||
{0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3},
|
||||
{0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653},
|
||||
{0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1},
|
||||
{0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
|
||||
{0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA},
|
||||
{0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA},
|
||||
{0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B},
|
||||
{0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E},
|
||||
{0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797},
|
||||
{0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C},
|
||||
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
|
||||
{0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB},
|
||||
{0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF},
|
||||
{0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31E3},
|
||||
{0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x4DBF},
|
||||
{0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C},
|
||||
{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19},
|
||||
{0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
|
||||
{0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4},
|
||||
{0x16FF0, 0x16FF1}, {0x17000, 0x187F7}, {0x18800, 0x18CD5},
|
||||
{0x18D00, 0x18D08}, {0x1B000, 0x1B11E}, {0x1B150, 0x1B152},
|
||||
{0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, {0x1F004, 0x1F004},
|
||||
{0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
|
||||
{0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248},
|
||||
{0x1F250, 0x1F251}, {0x1F260, 0x1F265}, {0x1F300, 0x1F320},
|
||||
{0x1F32D, 0x1F335}, {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393},
|
||||
{0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0},
|
||||
{0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440},
|
||||
{0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E},
|
||||
{0x1F550, 0x1F567}, {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596},
|
||||
{0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5},
|
||||
{0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2}, {0x1F6D5, 0x1F6D7},
|
||||
{0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB},
|
||||
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F978},
|
||||
{0x1F97A, 0x1F9CB}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA74},
|
||||
{0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA86}, {0x1FA90, 0x1FAA8},
|
||||
{0x1FAB0, 0x1FAB6}, {0x1FAC0, 0x1FAC2}, {0x1FAD0, 0x1FAD6},
|
||||
{0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
|
||||
}
|
||||
|
||||
var ambiguous = table{
|
||||
{0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
|
||||
{0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4},
|
||||
{0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
|
||||
{0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
|
||||
{0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
|
||||
{0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
|
||||
{0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
|
||||
{0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
|
||||
{0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
|
||||
{0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
|
||||
{0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
|
||||
{0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
|
||||
{0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
|
||||
{0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
|
||||
{0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
|
||||
{0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
|
||||
{0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
|
||||
{0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F},
|
||||
{0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1},
|
||||
{0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F},
|
||||
{0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016},
|
||||
{0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022},
|
||||
{0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033},
|
||||
{0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E},
|
||||
{0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084},
|
||||
{0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105},
|
||||
{0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116},
|
||||
{0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B},
|
||||
{0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B},
|
||||
{0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199},
|
||||
{0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4},
|
||||
{0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203},
|
||||
{0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F},
|
||||
{0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A},
|
||||
{0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225},
|
||||
{0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237},
|
||||
{0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C},
|
||||
{0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267},
|
||||
{0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283},
|
||||
{0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299},
|
||||
{0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312},
|
||||
{0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573},
|
||||
{0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1},
|
||||
{0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7},
|
||||
{0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8},
|
||||
{0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5},
|
||||
{0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609},
|
||||
{0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E},
|
||||
{0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661},
|
||||
{0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D},
|
||||
{0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF},
|
||||
{0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1},
|
||||
{0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1},
|
||||
{0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC},
|
||||
{0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F},
|
||||
{0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF},
|
||||
{0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A},
|
||||
{0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D},
|
||||
{0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
|
||||
{0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
|
||||
}
|
||||
var narrow = table{
|
||||
{0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6},
|
||||
{0x00AC, 0x00AC}, {0x00AF, 0x00AF}, {0x27E6, 0x27ED},
|
||||
{0x2985, 0x2986},
|
||||
}
|
||||
|
||||
var neutral = table{
|
||||
{0x0000, 0x001F}, {0x007F, 0x00A0}, {0x00A9, 0x00A9},
|
||||
{0x00AB, 0x00AB}, {0x00B5, 0x00B5}, {0x00BB, 0x00BB},
|
||||
{0x00C0, 0x00C5}, {0x00C7, 0x00CF}, {0x00D1, 0x00D6},
|
||||
{0x00D9, 0x00DD}, {0x00E2, 0x00E5}, {0x00E7, 0x00E7},
|
||||
{0x00EB, 0x00EB}, {0x00EE, 0x00EF}, {0x00F1, 0x00F1},
|
||||
{0x00F4, 0x00F6}, {0x00FB, 0x00FB}, {0x00FD, 0x00FD},
|
||||
{0x00FF, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112},
|
||||
{0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A},
|
||||
{0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E},
|
||||
{0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C},
|
||||
{0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A},
|
||||
{0x016C, 0x01CD}, {0x01CF, 0x01CF}, {0x01D1, 0x01D1},
|
||||
{0x01D3, 0x01D3}, {0x01D5, 0x01D5}, {0x01D7, 0x01D7},
|
||||
{0x01D9, 0x01D9}, {0x01DB, 0x01DB}, {0x01DD, 0x0250},
|
||||
{0x0252, 0x0260}, {0x0262, 0x02C3}, {0x02C5, 0x02C6},
|
||||
{0x02C8, 0x02C8}, {0x02CC, 0x02CC}, {0x02CE, 0x02CF},
|
||||
{0x02D1, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE},
|
||||
{0x02E0, 0x02FF}, {0x0370, 0x0377}, {0x037A, 0x037F},
|
||||
{0x0384, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x0390},
|
||||
{0x03AA, 0x03B0}, {0x03C2, 0x03C2}, {0x03CA, 0x0400},
|
||||
{0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F},
|
||||
{0x0531, 0x0556}, {0x0559, 0x058A}, {0x058D, 0x058F},
|
||||
{0x0591, 0x05C7}, {0x05D0, 0x05EA}, {0x05EF, 0x05F4},
|
||||
{0x0600, 0x061C}, {0x061E, 0x070D}, {0x070F, 0x074A},
|
||||
{0x074D, 0x07B1}, {0x07C0, 0x07FA}, {0x07FD, 0x082D},
|
||||
{0x0830, 0x083E}, {0x0840, 0x085B}, {0x085E, 0x085E},
|
||||
{0x0860, 0x086A}, {0x08A0, 0x08B4}, {0x08B6, 0x08C7},
|
||||
{0x08D3, 0x0983}, {0x0985, 0x098C}, {0x098F, 0x0990},
|
||||
{0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2},
|
||||
{0x09B6, 0x09B9}, {0x09BC, 0x09C4}, {0x09C7, 0x09C8},
|
||||
{0x09CB, 0x09CE}, {0x09D7, 0x09D7}, {0x09DC, 0x09DD},
|
||||
{0x09DF, 0x09E3}, {0x09E6, 0x09FE}, {0x0A01, 0x0A03},
|
||||
{0x0A05, 0x0A0A}, {0x0A0F, 0x0A10}, {0x0A13, 0x0A28},
|
||||
{0x0A2A, 0x0A30}, {0x0A32, 0x0A33}, {0x0A35, 0x0A36},
|
||||
{0x0A38, 0x0A39}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42},
|
||||
{0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51},
|
||||
{0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76},
|
||||
{0x0A81, 0x0A83}, {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91},
|
||||
{0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3},
|
||||
{0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9},
|
||||
{0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3},
|
||||
{0x0AE6, 0x0AF1}, {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03},
|
||||
{0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28},
|
||||
{0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B35, 0x0B39},
|
||||
{0x0B3C, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D},
|
||||
{0x0B55, 0x0B57}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63},
|
||||
{0x0B66, 0x0B77}, {0x0B82, 0x0B83}, {0x0B85, 0x0B8A},
|
||||
{0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A},
|
||||
{0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4},
|
||||
{0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2},
|
||||
{0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0},
|
||||
{0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C},
|
||||
{0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, {0x0C2A, 0x0C39},
|
||||
{0x0C3D, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D},
|
||||
{0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C63},
|
||||
{0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90},
|
||||
{0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
|
||||
{0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
|
||||
{0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3},
|
||||
{0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D00, 0x0D0C},
|
||||
{0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48},
|
||||
{0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F},
|
||||
{0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1},
|
||||
{0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6},
|
||||
{0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6},
|
||||
{0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4},
|
||||
{0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82},
|
||||
{0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3},
|
||||
{0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4},
|
||||
{0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9},
|
||||
{0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C},
|
||||
{0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC},
|
||||
{0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7},
|
||||
{0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248},
|
||||
{0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258},
|
||||
{0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
|
||||
{0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
|
||||
{0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6},
|
||||
{0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
|
||||
{0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5},
|
||||
{0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8},
|
||||
{0x1700, 0x170C}, {0x170E, 0x1714}, {0x1720, 0x1736},
|
||||
{0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770},
|
||||
{0x1772, 0x1773}, {0x1780, 0x17DD}, {0x17E0, 0x17E9},
|
||||
{0x17F0, 0x17F9}, {0x1800, 0x180E}, {0x1810, 0x1819},
|
||||
{0x1820, 0x1878}, {0x1880, 0x18AA}, {0x18B0, 0x18F5},
|
||||
{0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B},
|
||||
{0x1940, 0x1940}, {0x1944, 0x196D}, {0x1970, 0x1974},
|
||||
{0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA},
|
||||
{0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C},
|
||||
{0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD},
|
||||
{0x1AB0, 0x1AC0}, {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C},
|
||||
{0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49},
|
||||
{0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7},
|
||||
{0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9}, {0x1DFB, 0x1F15},
|
||||
{0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
|
||||
{0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
|
||||
{0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
|
||||
{0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
|
||||
{0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
|
||||
{0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017},
|
||||
{0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023},
|
||||
{0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034},
|
||||
{0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064},
|
||||
{0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080},
|
||||
{0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8},
|
||||
{0x20AA, 0x20AB}, {0x20AD, 0x20BF}, {0x20D0, 0x20F0},
|
||||
{0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108},
|
||||
{0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120},
|
||||
{0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152},
|
||||
{0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F},
|
||||
{0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7},
|
||||
{0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6},
|
||||
{0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206},
|
||||
{0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210},
|
||||
{0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C},
|
||||
{0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226},
|
||||
{0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B},
|
||||
{0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251},
|
||||
{0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269},
|
||||
{0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285},
|
||||
{0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4},
|
||||
{0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319},
|
||||
{0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF},
|
||||
{0x23F1, 0x23F2}, {0x23F4, 0x2426}, {0x2440, 0x244A},
|
||||
{0x24EA, 0x24EA}, {0x254C, 0x254F}, {0x2574, 0x257F},
|
||||
{0x2590, 0x2591}, {0x2596, 0x259F}, {0x25A2, 0x25A2},
|
||||
{0x25AA, 0x25B1}, {0x25B4, 0x25B5}, {0x25B8, 0x25BB},
|
||||
{0x25BE, 0x25BF}, {0x25C2, 0x25C5}, {0x25C9, 0x25CA},
|
||||
{0x25CC, 0x25CD}, {0x25D2, 0x25E1}, {0x25E6, 0x25EE},
|
||||
{0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608},
|
||||
{0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B},
|
||||
{0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641},
|
||||
{0x2643, 0x2647}, {0x2654, 0x265F}, {0x2662, 0x2662},
|
||||
{0x2666, 0x2666}, {0x266B, 0x266B}, {0x266E, 0x266E},
|
||||
{0x2670, 0x267E}, {0x2680, 0x2692}, {0x2694, 0x269D},
|
||||
{0x26A0, 0x26A0}, {0x26A2, 0x26A9}, {0x26AC, 0x26BC},
|
||||
{0x26C0, 0x26C3}, {0x26E2, 0x26E2}, {0x26E4, 0x26E7},
|
||||
{0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727},
|
||||
{0x2729, 0x273C}, {0x273E, 0x274B}, {0x274D, 0x274D},
|
||||
{0x274F, 0x2752}, {0x2756, 0x2756}, {0x2758, 0x2775},
|
||||
{0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE},
|
||||
{0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A},
|
||||
{0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73},
|
||||
{0x2B76, 0x2B95}, {0x2B97, 0x2C2E}, {0x2C30, 0x2C5E},
|
||||
{0x2C60, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D27, 0x2D27},
|
||||
{0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D70},
|
||||
{0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
|
||||
{0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6},
|
||||
{0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
|
||||
{0x2DE0, 0x2E52}, {0x303F, 0x303F}, {0x4DC0, 0x4DFF},
|
||||
{0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, {0xA700, 0xA7BF},
|
||||
{0xA7C2, 0xA7CA}, {0xA7F5, 0xA82C}, {0xA830, 0xA839},
|
||||
{0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9},
|
||||
{0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD},
|
||||
{0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
|
||||
{0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
|
||||
{0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
|
||||
{0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E},
|
||||
{0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
|
||||
{0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF},
|
||||
{0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
|
||||
{0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41},
|
||||
{0xFB43, 0xFB44}, {0xFB46, 0xFBC1}, {0xFBD3, 0xFD3F},
|
||||
{0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD},
|
||||
{0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC},
|
||||
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B},
|
||||
{0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D},
|
||||
{0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA},
|
||||
{0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E},
|
||||
{0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD},
|
||||
{0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB},
|
||||
{0x10300, 0x10323}, {0x1032D, 0x1034A}, {0x10350, 0x1037A},
|
||||
{0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
|
||||
{0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3},
|
||||
{0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
|
||||
{0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755},
|
||||
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808},
|
||||
{0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C},
|
||||
{0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
|
||||
{0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B},
|
||||
{0x1091F, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x109B7},
|
||||
{0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06},
|
||||
{0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
|
||||
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58},
|
||||
{0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6},
|
||||
{0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
|
||||
{0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
|
||||
{0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
|
||||
{0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10E60, 0x10E7E},
|
||||
{0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EB0, 0x10EB1},
|
||||
{0x10F00, 0x10F27}, {0x10F30, 0x10F59}, {0x10FB0, 0x10FCB},
|
||||
{0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x1106F},
|
||||
{0x1107F, 0x110C1}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
|
||||
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147},
|
||||
{0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
|
||||
{0x11200, 0x11211}, {0x11213, 0x1123E}, {0x11280, 0x11286},
|
||||
{0x11288, 0x11288}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D},
|
||||
{0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
|
||||
{0x11300, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310},
|
||||
{0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333},
|
||||
{0x11335, 0x11339}, {0x1133B, 0x11344}, {0x11347, 0x11348},
|
||||
{0x1134B, 0x1134D}, {0x11350, 0x11350}, {0x11357, 0x11357},
|
||||
{0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
|
||||
{0x11400, 0x1145B}, {0x1145D, 0x11461}, {0x11480, 0x114C7},
|
||||
{0x114D0, 0x114D9}, {0x11580, 0x115B5}, {0x115B8, 0x115DD},
|
||||
{0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C},
|
||||
{0x11680, 0x116B8}, {0x116C0, 0x116C9}, {0x11700, 0x1171A},
|
||||
{0x1171D, 0x1172B}, {0x11730, 0x1173F}, {0x11800, 0x1183B},
|
||||
{0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x11909, 0x11909},
|
||||
{0x1190C, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x11935},
|
||||
{0x11937, 0x11938}, {0x1193B, 0x11946}, {0x11950, 0x11959},
|
||||
{0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4},
|
||||
{0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AC0, 0x11AF8},
|
||||
{0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45},
|
||||
{0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
|
||||
{0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09},
|
||||
{0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D},
|
||||
{0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65},
|
||||
{0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91},
|
||||
{0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8},
|
||||
{0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
|
||||
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
|
||||
{0x13000, 0x1342E}, {0x13430, 0x13438}, {0x14400, 0x14646},
|
||||
{0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69},
|
||||
{0x16A6E, 0x16A6F}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5},
|
||||
{0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61},
|
||||
{0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16E40, 0x16E9A},
|
||||
{0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F},
|
||||
{0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88},
|
||||
{0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, {0x1D000, 0x1D0F5},
|
||||
{0x1D100, 0x1D126}, {0x1D129, 0x1D1E8}, {0x1D200, 0x1D245},
|
||||
{0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356}, {0x1D360, 0x1D378},
|
||||
{0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F},
|
||||
{0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC},
|
||||
{0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3},
|
||||
{0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514},
|
||||
{0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
|
||||
{0x1D540, 0x1D544}, {0x1D546, 0x1D546}, {0x1D54A, 0x1D550},
|
||||
{0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B},
|
||||
{0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006},
|
||||
{0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
|
||||
{0x1E026, 0x1E02A}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D},
|
||||
{0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E2C0, 0x1E2F9},
|
||||
{0x1E2FF, 0x1E2FF}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6},
|
||||
{0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F},
|
||||
{0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03},
|
||||
{0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24},
|
||||
{0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37},
|
||||
{0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, {0x1EE42, 0x1EE42},
|
||||
{0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, {0x1EE4B, 0x1EE4B},
|
||||
{0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, {0x1EE54, 0x1EE54},
|
||||
{0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, {0x1EE5B, 0x1EE5B},
|
||||
{0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, {0x1EE61, 0x1EE62},
|
||||
{0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
|
||||
{0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE7E, 0x1EE7E},
|
||||
{0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3},
|
||||
{0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1},
|
||||
{0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093},
|
||||
{0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE},
|
||||
{0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F}, {0x1F12E, 0x1F12F},
|
||||
{0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD}, {0x1F1E6, 0x1F1FF},
|
||||
{0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D},
|
||||
{0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF},
|
||||
{0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F},
|
||||
{0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A},
|
||||
{0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594},
|
||||
{0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F},
|
||||
{0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4},
|
||||
{0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773},
|
||||
{0x1F780, 0x1F7D8}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
|
||||
{0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD},
|
||||
{0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B},
|
||||
{0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D},
|
||||
{0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9},
|
||||
{0xE0001, 0xE0001}, {0xE0020, 0xE007F},
|
||||
}
|
||||
|
||||
var emoji = table{
|
||||
{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
|
||||
{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
|
||||
{0x231A, 0x231B}, {0x2328, 0x2328}, {0x2388, 0x2388},
|
||||
{0x23CF, 0x23CF}, {0x23E9, 0x23F3}, {0x23F8, 0x23FA},
|
||||
{0x24C2, 0x24C2}, {0x25AA, 0x25AB}, {0x25B6, 0x25B6},
|
||||
{0x25C0, 0x25C0}, {0x25FB, 0x25FE}, {0x2600, 0x2605},
|
||||
{0x2607, 0x2612}, {0x2614, 0x2685}, {0x2690, 0x2705},
|
||||
{0x2708, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
|
||||
{0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
|
||||
{0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
|
||||
{0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
|
||||
{0x2757, 0x2757}, {0x2763, 0x2767}, {0x2795, 0x2797},
|
||||
{0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
|
||||
{0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
|
||||
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
|
||||
{0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
|
||||
{0x1F000, 0x1F0FF}, {0x1F10D, 0x1F10F}, {0x1F12F, 0x1F12F},
|
||||
{0x1F16C, 0x1F171}, {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E},
|
||||
{0x1F191, 0x1F19A}, {0x1F1AD, 0x1F1E5}, {0x1F201, 0x1F20F},
|
||||
{0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A},
|
||||
{0x1F23C, 0x1F23F}, {0x1F249, 0x1F3FA}, {0x1F400, 0x1F53D},
|
||||
{0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F},
|
||||
{0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F},
|
||||
{0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF},
|
||||
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FAFF},
|
||||
{0x1FC00, 0x1FFFD},
|
||||
}
|
||||
28
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
28
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// +build windows
|
||||
// +build !appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
||||
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
|
||||
)
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
r1, _, _ := procGetConsoleOutputCP.Call()
|
||||
if r1 == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch int(r1) {
|
||||
case 932, 51932, 936, 949, 950:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
8
vendor/github.com/moby/term/.gitignore
generated
vendored
Normal file
8
vendor/github.com/moby/term/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# if you want to ignore files created by your editor/tools, consider using a
|
||||
# global .gitignore or .git/info/exclude see https://help.github.com/articles/ignoring-files
|
||||
.*
|
||||
!.github
|
||||
!.gitignore
|
||||
profile.out
|
||||
# support running go modules in vendor mode for local development
|
||||
vendor/
|
||||
191
vendor/github.com/moby/term/LICENSE
generated
vendored
Normal file
191
vendor/github.com/moby/term/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2013-2018 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
36
vendor/github.com/moby/term/README.md
generated
vendored
Normal file
36
vendor/github.com/moby/term/README.md
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# term - utilities for dealing with terminals
|
||||
|
||||
 [](https://godoc.org/github.com/moby/term) [](https://goreportcard.com/report/github.com/moby/term)
|
||||
|
||||
term provides structures and helper functions to work with terminal (state, sizes).
|
||||
|
||||
#### Using term
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fd := os.Stdin.Fd()
|
||||
if term.IsTerminal(fd) {
|
||||
ws, err := term.GetWinsize(fd)
|
||||
if err != nil {
|
||||
log.Fatalf("term.GetWinsize: %s", err)
|
||||
}
|
||||
log.Printf("%d:%d\n", ws.Height, ws.Width)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to hack on term? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply.
|
||||
|
||||
## Copyright and license
|
||||
Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons.
|
||||
@@ -1,4 +1,4 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
package term
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
88
vendor/github.com/moby/term/proxy.go
generated
vendored
Normal file
88
vendor/github.com/moby/term/proxy.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// EscapeError is special error which returned by a TTY proxy reader's Read()
|
||||
// method in case its detach escape sequence is read.
|
||||
type EscapeError struct{}
|
||||
|
||||
func (EscapeError) Error() string {
|
||||
return "read escape sequence"
|
||||
}
|
||||
|
||||
// escapeProxy is used only for attaches with a TTY. It is used to proxy
|
||||
// stdin keypresses from the underlying reader and look for the passed in
|
||||
// escape key sequence to signal a detach.
|
||||
type escapeProxy struct {
|
||||
escapeKeys []byte
|
||||
escapeKeyPos int
|
||||
r io.Reader
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
|
||||
// and detects when the specified escape keys are read, in which case the Read
|
||||
// method will return an error of type EscapeError.
|
||||
func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader {
|
||||
return &escapeProxy{
|
||||
escapeKeys: escapeKeys,
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *escapeProxy) Read(buf []byte) (n int, err error) {
|
||||
if len(r.escapeKeys) > 0 && r.escapeKeyPos == len(r.escapeKeys) {
|
||||
return 0, EscapeError{}
|
||||
}
|
||||
|
||||
if len(r.buf) > 0 {
|
||||
n = copy(buf, r.buf)
|
||||
r.buf = r.buf[n:]
|
||||
}
|
||||
|
||||
nr, err := r.r.Read(buf[n:])
|
||||
n += nr
|
||||
if len(r.escapeKeys) == 0 {
|
||||
return n, err
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if buf[i] == r.escapeKeys[r.escapeKeyPos] {
|
||||
r.escapeKeyPos++
|
||||
|
||||
// Check if the full escape sequence is matched.
|
||||
if r.escapeKeyPos == len(r.escapeKeys) {
|
||||
n = i + 1 - r.escapeKeyPos
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
return n, EscapeError{}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// If we need to prepend a partial escape sequence from the previous
|
||||
// read, make sure the new buffer size doesn't exceed len(buf).
|
||||
// Otherwise, preserve any extra data in a buffer for the next read.
|
||||
if i < r.escapeKeyPos {
|
||||
preserve := make([]byte, 0, r.escapeKeyPos+n)
|
||||
preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...)
|
||||
preserve = append(preserve, buf[:n]...)
|
||||
n = copy(buf, preserve)
|
||||
i += r.escapeKeyPos
|
||||
r.buf = append(r.buf, preserve[n:]...)
|
||||
}
|
||||
r.escapeKeyPos = 0
|
||||
}
|
||||
|
||||
// If we're in the middle of reading an escape sequence, make sure we don't
|
||||
// let the caller read it. If later on we find that this is not the escape
|
||||
// sequence, we'll prepend it back to buf.
|
||||
n -= r.escapeKeyPos
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
19
vendor/github.com/moby/term/tc.go
generated
vendored
Normal file
19
vendor/github.com/moby/term/tc.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build !windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func tcget(fd uintptr) (*Termios, error) {
|
||||
p, err := unix.IoctlGetTermios(int(fd), getTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func tcset(fd uintptr, p *Termios) error {
|
||||
return unix.IoctlSetTermios(int(fd), setTermios, p)
|
||||
}
|
||||
20
vendor/github.com/docker/docker/pkg/term/term.go → vendor/github.com/moby/term/term.go
generated
vendored
20
vendor/github.com/docker/docker/pkg/term/term.go → vendor/github.com/moby/term/term.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
// Package term provides structures and helper functions to work with
|
||||
// terminal (state, sizes).
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
package term
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -50,8 +50,8 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios Termios
|
||||
return tcget(fd, &termios) == 0
|
||||
_, err := tcget(fd)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||
@@ -60,20 +60,16 @@ func RestoreTerminal(fd uintptr, state *State) error {
|
||||
if state == nil {
|
||||
return ErrInvalidState
|
||||
}
|
||||
if err := tcset(fd, &state.termios); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return tcset(fd, &state.termios)
|
||||
}
|
||||
|
||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||
func SaveState(fd uintptr) (*State, error) {
|
||||
var oldState State
|
||||
if err := tcget(fd, &oldState.termios); err != 0 {
|
||||
termios, err := tcget(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
return &State{termios: *termios}, nil
|
||||
}
|
||||
|
||||
// DisableEcho applies the specified state to the terminal connected to the file
|
||||
@@ -82,7 +78,7 @@ func DisableEcho(fd uintptr, state *State) error {
|
||||
newState := state.termios
|
||||
newState.Lflag &^= unix.ECHO
|
||||
|
||||
if err := tcset(fd, &newState); err != 0 {
|
||||
if err := tcset(fd, &newState); err != nil {
|
||||
return err
|
||||
}
|
||||
handleInterrupt(fd, state)
|
||||
@@ -1,13 +1,12 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
package term
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE
|
||||
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
"github.com/docker/docker/pkg/term/windows"
|
||||
windowsconsole "github.com/moby/term/windows"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// State holds the console mode for the terminal.
|
||||
@@ -28,58 +27,62 @@ var vtInputSupported bool
|
||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
||||
// Turn on VT handling on all std handles, if possible. This might
|
||||
// fail, in which case we will fall back to terminal emulation.
|
||||
var emulateStdin, emulateStdout, emulateStderr bool
|
||||
fd := os.Stdin.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
var (
|
||||
emulateStdin, emulateStdout, emulateStderr bool
|
||||
|
||||
mode uint32
|
||||
)
|
||||
|
||||
fd := windows.Handle(os.Stdin.Fd())
|
||||
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||
// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
|
||||
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
|
||||
emulateStdin = true
|
||||
} else {
|
||||
vtInputSupported = true
|
||||
}
|
||||
// Unconditionally set the console mode back even on failure because SetConsoleMode
|
||||
// remembers invalid bits on input handles.
|
||||
winterm.SetConsoleMode(fd, mode)
|
||||
_ = windows.SetConsoleMode(fd, mode)
|
||||
}
|
||||
|
||||
fd = os.Stdout.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
fd = windows.Handle(os.Stdout.Fd())
|
||||
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
emulateStdout = true
|
||||
} else {
|
||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
}
|
||||
}
|
||||
|
||||
fd = os.Stderr.Fd()
|
||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
||||
fd = windows.Handle(os.Stderr.Fd())
|
||||
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||
emulateStderr = true
|
||||
} else {
|
||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
}
|
||||
}
|
||||
|
||||
// Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and
|
||||
// STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as
|
||||
// go-ansiterm hasn't switch to x/sys/windows.
|
||||
// TODO: switch back to x/sys/windows once go-ansiterm has switched
|
||||
if emulateStdin {
|
||||
stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE)
|
||||
h := uint32(windows.STD_INPUT_HANDLE)
|
||||
stdIn = windowsconsole.NewAnsiReader(int(h))
|
||||
} else {
|
||||
stdIn = os.Stdin
|
||||
}
|
||||
|
||||
if emulateStdout {
|
||||
stdOut = windowsconsole.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE)
|
||||
h := uint32(windows.STD_OUTPUT_HANDLE)
|
||||
stdOut = windowsconsole.NewAnsiWriter(int(h))
|
||||
} else {
|
||||
stdOut = os.Stdout
|
||||
}
|
||||
|
||||
if emulateStderr {
|
||||
stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE)
|
||||
h := uint32(windows.STD_ERROR_HANDLE)
|
||||
stdErr = windowsconsole.NewAnsiWriter(int(h))
|
||||
} else {
|
||||
stdErr = os.Stderr
|
||||
}
|
||||
@@ -94,8 +97,8 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
|
||||
|
||||
// GetWinsize returns the window size based on the specified file descriptor.
|
||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
||||
if err != nil {
|
||||
var info windows.ConsoleScreenBufferInfo
|
||||
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -109,20 +112,23 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return windowsconsole.IsConsole(fd)
|
||||
var mode uint32
|
||||
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||
// to a previous state.
|
||||
func RestoreTerminal(fd uintptr, state *State) error {
|
||||
return winterm.SetConsoleMode(fd, state.mode)
|
||||
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
|
||||
}
|
||||
|
||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||
func SaveState(fd uintptr) (*State, error) {
|
||||
mode, e := winterm.GetConsoleMode(fd)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
var mode uint32
|
||||
|
||||
if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &State{mode: mode}, nil
|
||||
@@ -132,9 +138,9 @@ func SaveState(fd uintptr) (*State, error) {
|
||||
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||
func DisableEcho(fd uintptr, state *State) error {
|
||||
mode := state.mode
|
||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
||||
mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT
|
||||
err := winterm.SetConsoleMode(fd, mode)
|
||||
mode &^= windows.ENABLE_ECHO_INPUT
|
||||
mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
|
||||
err := windows.SetConsoleMode(windows.Handle(fd), mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -169,7 +175,7 @@ func SetRawTerminalOutput(fd uintptr) (*State, error) {
|
||||
|
||||
// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
|
||||
// version of Windows.
|
||||
winterm.SetConsoleMode(fd, state.mode|winterm.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
_ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
return state, err
|
||||
}
|
||||
|
||||
@@ -188,21 +194,21 @@ func MakeRaw(fd uintptr) (*State, error) {
|
||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||
|
||||
// Disable these modes
|
||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
||||
mode &^= winterm.ENABLE_LINE_INPUT
|
||||
mode &^= winterm.ENABLE_MOUSE_INPUT
|
||||
mode &^= winterm.ENABLE_WINDOW_INPUT
|
||||
mode &^= winterm.ENABLE_PROCESSED_INPUT
|
||||
mode &^= windows.ENABLE_ECHO_INPUT
|
||||
mode &^= windows.ENABLE_LINE_INPUT
|
||||
mode &^= windows.ENABLE_MOUSE_INPUT
|
||||
mode &^= windows.ENABLE_WINDOW_INPUT
|
||||
mode &^= windows.ENABLE_PROCESSED_INPUT
|
||||
|
||||
// Enable these modes
|
||||
mode |= winterm.ENABLE_EXTENDED_FLAGS
|
||||
mode |= winterm.ENABLE_INSERT_MODE
|
||||
mode |= winterm.ENABLE_QUICK_EDIT_MODE
|
||||
mode |= windows.ENABLE_EXTENDED_FLAGS
|
||||
mode |= windows.ENABLE_INSERT_MODE
|
||||
mode |= windows.ENABLE_QUICK_EDIT_MODE
|
||||
if vtInputSupported {
|
||||
mode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||
mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||
}
|
||||
|
||||
err = winterm.SetConsoleMode(fd, mode)
|
||||
err = windows.SetConsoleMode(windows.Handle(fd), mode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,7 +221,7 @@ func restoreAtInterrupt(fd uintptr, state *State) {
|
||||
|
||||
go func() {
|
||||
_ = <-sigchan
|
||||
RestoreTerminal(fd, state)
|
||||
_ = RestoreTerminal(fd, state)
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
@@ -1,28 +1,24 @@
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
// +build !windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TCGETS
|
||||
setTermios = unix.TCSETS
|
||||
)
|
||||
|
||||
// Termios is the Unix API for terminal I/O.
|
||||
type Termios unix.Termios
|
||||
type Termios = unix.Termios
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// MakeRaw puts the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd uintptr) (*State, error) {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), getTermios)
|
||||
termios, err := tcget(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var oldState State
|
||||
oldState.termios = Termios(*termios)
|
||||
oldState := State{termios: *termios}
|
||||
|
||||
termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
termios.Oflag &^= unix.OPOST
|
||||
@@ -32,7 +28,7 @@ func MakeRaw(fd uintptr) (*State, error) {
|
||||
termios.Cc[unix.VMIN] = 1
|
||||
termios.Cc[unix.VTIME] = 0
|
||||
|
||||
if err := unix.IoctlSetTermios(int(fd), setTermios, termios); err != nil {
|
||||
if err := tcset(fd, termios); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &oldState, nil
|
||||
12
vendor/github.com/moby/term/termios_bsd.go
generated
vendored
Normal file
12
vendor/github.com/moby/term/termios_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build darwin freebsd openbsd netbsd
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TIOCGETA
|
||||
setTermios = unix.TIOCSETA
|
||||
)
|
||||
12
vendor/github.com/moby/term/termios_nonbsd.go
generated
vendored
Normal file
12
vendor/github.com/moby/term/termios_nonbsd.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//+build !darwin,!freebsd,!netbsd,!openbsd,!windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = unix.TCGETS
|
||||
setTermios = unix.TCSETS
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
package windowsconsole
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -31,7 +31,6 @@ type ansiReader struct {
|
||||
// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a
|
||||
// Windows console input handle.
|
||||
func NewAnsiReader(nFile int) io.ReadCloser {
|
||||
initLogger()
|
||||
file, fd := winterm.GetStdFile(nFile)
|
||||
return &ansiReader{
|
||||
file: file,
|
||||
@@ -59,8 +58,6 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||
|
||||
// Previously read bytes exist, read as much as we can and return
|
||||
if len(ar.buffer) > 0 {
|
||||
logger.Debugf("Reading previously cached bytes")
|
||||
|
||||
originalLength := len(ar.buffer)
|
||||
copiedLength := copy(p, ar.buffer)
|
||||
|
||||
@@ -70,16 +67,14 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||
ar.buffer = ar.buffer[copiedLength:]
|
||||
}
|
||||
|
||||
logger.Debugf("Read from cache p[%d]: % x", copiedLength, p)
|
||||
return copiedLength, nil
|
||||
}
|
||||
|
||||
// Read and translate key events
|
||||
events, err := readInputEvents(ar.fd, len(p))
|
||||
events, err := readInputEvents(ar, len(p))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if len(events) == 0 {
|
||||
logger.Debug("No input events detected")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -87,11 +82,9 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||
|
||||
// Save excess bytes and right-size keyBytes
|
||||
if len(keyBytes) > len(p) {
|
||||
logger.Debugf("Received %d keyBytes, only room for %d bytes", len(keyBytes), len(p))
|
||||
ar.buffer = keyBytes[len(p):]
|
||||
keyBytes = keyBytes[:len(p)]
|
||||
} else if len(keyBytes) == 0 {
|
||||
logger.Debug("No key bytes returned from the translator")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -100,13 +93,11 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||
return 0, errors.New("unexpected copy length encountered")
|
||||
}
|
||||
|
||||
logger.Debugf("Read p[%d]: % x", copiedLength, p)
|
||||
logger.Debugf("Read keyBytes[%d]: % x", copiedLength, keyBytes)
|
||||
return copiedLength, nil
|
||||
}
|
||||
|
||||
// readInputEvents polls until at least one event is available.
|
||||
func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||
func readInputEvents(ar *ansiReader, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||
// Determine the maximum number of records to retrieve
|
||||
// -- Cast around the type system to obtain the size of a single INPUT_RECORD.
|
||||
// unsafe.Sizeof requires an expression vs. a type-reference; the casting
|
||||
@@ -118,25 +109,23 @@ func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||
} else if countRecords == 0 {
|
||||
countRecords = 1
|
||||
}
|
||||
logger.Debugf("[windows] readInputEvents: Reading %v records (buffer size %v, record size %v)", countRecords, maxBytes, recordSize)
|
||||
|
||||
// Wait for and read input events
|
||||
events := make([]winterm.INPUT_RECORD, countRecords)
|
||||
nEvents := uint32(0)
|
||||
eventsExist, err := winterm.WaitForSingleObject(fd, winterm.WAIT_INFINITE)
|
||||
eventsExist, err := winterm.WaitForSingleObject(ar.fd, winterm.WAIT_INFINITE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if eventsExist {
|
||||
err = winterm.ReadConsoleInput(fd, events, &nEvents)
|
||||
err = winterm.ReadConsoleInput(ar.fd, events, &nEvents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Return a slice restricted to the number of returned records
|
||||
logger.Debugf("[windows] readInputEvents: Read %v events", nEvents)
|
||||
return events[:nEvents], nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
package windowsconsole
|
||||
|
||||
import (
|
||||
"io"
|
||||
@@ -24,7 +24,6 @@ type ansiWriter struct {
|
||||
// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
|
||||
// Windows console output handle.
|
||||
func NewAnsiWriter(nFile int) io.Writer {
|
||||
initLogger()
|
||||
file, fd := winterm.GetStdFile(nFile)
|
||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
||||
if err != nil {
|
||||
@@ -32,9 +31,8 @@ func NewAnsiWriter(nFile int) io.Writer {
|
||||
}
|
||||
|
||||
parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
|
||||
logger.Infof("newAnsiWriter: parser %p", parser)
|
||||
|
||||
aw := &ansiWriter{
|
||||
return &ansiWriter{
|
||||
file: file,
|
||||
fd: fd,
|
||||
infoReset: info,
|
||||
@@ -42,10 +40,6 @@ func NewAnsiWriter(nFile int) io.Writer {
|
||||
escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
|
||||
parser: parser,
|
||||
}
|
||||
|
||||
logger.Infof("newAnsiWriter: aw.parser %p", aw.parser)
|
||||
logger.Infof("newAnsiWriter: %v", aw)
|
||||
return aw
|
||||
}
|
||||
|
||||
func (aw *ansiWriter) Fd() uintptr {
|
||||
@@ -58,7 +52,5 @@ func (aw *ansiWriter) Write(p []byte) (total int, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
logger.Infof("Write: % x", p)
|
||||
logger.Infof("Write: %s", string(p))
|
||||
return aw.parser.Parse(p)
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
// +build windows
|
||||
|
||||
package windowsconsole // import "github.com/docker/docker/pkg/term/windows"
|
||||
package windowsconsole
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
|
||||
@@ -22,14 +22,18 @@ func GetHandleInfo(in interface{}) (uintptr, bool) {
|
||||
|
||||
if file, ok := in.(*os.File); ok {
|
||||
inFd = file.Fd()
|
||||
isTerminal = IsConsole(inFd)
|
||||
isTerminal = isConsole(inFd)
|
||||
}
|
||||
return inFd, isTerminal
|
||||
}
|
||||
|
||||
// IsConsole returns true if the given file descriptor is a Windows Console.
|
||||
// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
|
||||
func IsConsole(fd uintptr) bool {
|
||||
_, e := winterm.GetConsoleMode(fd)
|
||||
return e == nil
|
||||
// Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/term.IsTerminal()
|
||||
var IsConsole = isConsole
|
||||
|
||||
func isConsole(fd uintptr) bool {
|
||||
var mode uint32
|
||||
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
|
||||
return err == nil
|
||||
}
|
||||
5
vendor/github.com/moby/term/windows/doc.go
generated
vendored
Normal file
5
vendor/github.com/moby/term/windows/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
|
||||
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
|
||||
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
|
||||
|
||||
package windowsconsole
|
||||
@@ -1,6 +1,6 @@
|
||||
// +build !windows
|
||||
|
||||
package term // import "github.com/docker/docker/pkg/term"
|
||||
package term
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
15
vendor/github.com/olekukonko/tablewriter/.gitignore
generated
vendored
Normal file
15
vendor/github.com/olekukonko/tablewriter/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Go template
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
22
vendor/github.com/olekukonko/tablewriter/.travis.yml
generated
vendored
Normal file
22
vendor/github.com/olekukonko/tablewriter/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
language: go
|
||||
arch:
|
||||
- ppc64le
|
||||
- amd64
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- "1.10"
|
||||
- tip
|
||||
jobs:
|
||||
exclude :
|
||||
- arch : ppc64le
|
||||
go :
|
||||
- 1.3
|
||||
- arch : ppc64le
|
||||
go :
|
||||
- 1.4
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user