cli: add monitor flag to deployment status

Adding '-verbose' will print out the allocation information for the
deployment. This also changes the job run command so that it now blocks
until deployment is complete and adds timestamps to the output so that
it's more in line with the output of node drain.

This uses glint to print in place in running in a tty. Because glint
doesn't yet support cmd/powershell, Windows workflows use a different
library to print in place, which results in slightly different
formatting: 1) different margins, and 2) no spinner indicating
deployment in progress.
This commit is contained in:
Isabel Suchanek
2021-05-20 16:19:39 -07:00
committed by Isabel Suchanek
parent 66d590c64b
commit 0edda116ad
111 changed files with 13434 additions and 165 deletions

2
vendor/github.com/VividCortex/ewma/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
.DS_Store
.*.sw?

21
vendor/github.com/VividCortex/ewma/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License
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
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.

140
vendor/github.com/VividCortex/ewma/README.md generated vendored Normal file
View File

@@ -0,0 +1,140 @@
# EWMA [![GoDoc](https://godoc.org/github.com/VividCortex/ewma?status.svg)](https://godoc.org/github.com/VividCortex/ewma) ![Build Status](https://circleci.com/gh/VividCortex/moving_average.png?circle-token=1459fa37f9ca0e50cef05d1963146d96d47ea523)
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.
![Data Series](https://user-images.githubusercontent.com/279875/28242350-463289a2-6977-11e7-88ca-fd778ccef1f0.png)
Now let's take the moving average of those numbers. First we set the average to the value
of the first number.
![EWMA Step 1](https://user-images.githubusercontent.com/279875/28242353-464c96bc-6977-11e7-9981-dc4e0789c7ba.png)
Next we multiply the next number by alpha, multiply the current value by 1-alpha, and add
them to generate a new value.
![EWMA Step 2](https://user-images.githubusercontent.com/279875/28242351-464abefa-6977-11e7-95d0-43900f29bef2.png)
This continues until we are done.
![EWMA Step N](https://user-images.githubusercontent.com/279875/28242352-464c58f0-6977-11e7-8cd0-e01e4efaac7f.png)
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.

126
vendor/github.com/VividCortex/ewma/ewma.go generated vendored Normal file
View 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
}
}

12
vendor/github.com/cheggaaa/pb/v3/LICENSE generated vendored Normal file
View 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.

290
vendor/github.com/cheggaaa/pb/v3/element.go generated vendored Normal file
View File

@@ -0,0 +1,290 @@
package pb
import (
"bytes"
"fmt"
"math"
"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]
for i := 0; i < repeat; i++ {
p.buf.Write(p.eb[eln])
}
StripStringToBuffer(string(p.eb[eln]), width%p.cc[eln], 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()
}
// 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 {
var rts string
sp := getSpeedObj(state).value(state)
if !state.IsFinished() {
if sp > 0 {
remain := float64(state.Total() - state.Value())
remainDur := time.Duration(remain/sp) * time.Second
rts = remainDur.String()
} else {
return argsHelper(args).getOr(2, "?")
}
} else {
rts = state.Time().Truncate(time.Second).Sub(state.StartTime().Truncate(time.Second)).String()
return fmt.Sprintf(argsHelper(args).getOr(1, "%s"), rts)
}
return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), rts)
}
// ElementElapsedTime shows elapsed time
// Optionally cat 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 {
etm := state.Time().Truncate(time.Second).Sub(state.StartTime().Truncate(time.Second))
return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), etm.String())
}
// 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]
}

11
vendor/github.com/cheggaaa/pb/v3/go.mod generated vendored Normal file
View File

@@ -0,0 +1,11 @@
module github.com/cheggaaa/pb/v3
require (
github.com/VividCortex/ewma v1.1.1
github.com/fatih/color v1.7.0
github.com/mattn/go-colorable v0.1.2
github.com/mattn/go-isatty v0.0.12
github.com/mattn/go-runewidth v0.0.7
)
go 1.12

21
vendor/github.com/cheggaaa/pb/v3/go.sum generated vendored Normal file
View File

@@ -0,0 +1,21 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

49
vendor/github.com/cheggaaa/pb/v3/io.go generated vendored Normal file
View 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
}

566
vendor/github.com/cheggaaa/pb/v3/pb.go generated vendored Normal file
View File

@@ -0,0 +1,566 @@
package pb
import (
"bytes"
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"sync/atomic"
"text/template"
"time"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"github.com/cheggaaa/pb/v3/termutil"
)
// Version of ProgressBar library
const Version = "3.0.5"
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
)
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 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" {
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
}
// 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
}
// 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
}

15
vendor/github.com/cheggaaa/pb/v3/preset.go generated vendored Normal file
View 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 = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }} {{speed . }} {{rtime . "ETA %s"}}{{string . "suffix"}}`
// Default - preset like Full but without elapsed time
// Example: 'Prefix 20/100 [-->______] 20% 1 p/s ETA 1m Suffix'
Default ProgressBarTemplate = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }} {{speed . }}{{string . "suffix"}}`
// Simple - preset without speed and any timers. Only counters, bar and percents
// Example: 'Prefix 20/100 [-->______] 20% Suffix'
Simple ProgressBarTemplate = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }}{{string . "suffix"}}`
)

83
vendor/github.com/cheggaaa/pb/v3/speed.go generated vendored Normal file
View 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))))
}

88
vendor/github.com/cheggaaa/pb/v3/template.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
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 {
emf[k] = v
}
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))]
}

56
vendor/github.com/cheggaaa/pb/v3/termutil/term.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package termutil
import (
"errors"
"os"
"os/signal"
"sync"
)
var echoLocked bool
var echoLockMutex sync.Mutex
var errLocked = errors.New("terminal locked")
// 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)
signal.Notify(sig, unlockSignals...)
defer signal.Stop(sig)
select {
case <-quit:
RawModeOff()
case <-sig:
RawModeOff()
}
}

View File

@@ -0,0 +1,11 @@
// +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")
}

View File

@@ -0,0 +1,9 @@
// +build darwin freebsd netbsd openbsd dragonfly
// +build !appengine
package termutil
import "syscall"
const ioctlReadTermios = syscall.TIOCGETA
const ioctlWriteTermios = syscall.TIOCSETA

View File

@@ -0,0 +1,7 @@
// +build linux
// +build !appengine
package termutil
const ioctlReadTermios = 0x5401 // syscall.TCGETS
const ioctlWriteTermios = 0x5402 // syscall.TCSETS

View File

@@ -0,0 +1,8 @@
// +build linux darwin freebsd netbsd openbsd dragonfly
// +build !appengine
package termutil
import "syscall"
const sysIoctl = syscall.SYS_IOCTL

View 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
}

View File

@@ -0,0 +1,8 @@
// +build solaris
// +build !appengine
package termutil
const ioctlReadTermios = 0x5401 // syscall.TCGETS
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
const sysIoctl = 54

155
vendor/github.com/cheggaaa/pb/v3/termutil/term_win.go generated vendored Normal file
View File

@@ -0,0 +1,155 @@
// +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
}

76
vendor/github.com/cheggaaa/pb/v3/termutil/term_x.go generated vendored Normal file
View File

@@ -0,0 +1,76 @@
// +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,
}
)
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) {
w := new(window)
res, _, err := syscall.Syscall(sysIoctl,
tty.Fd(),
uintptr(syscall.TIOCGWINSZ),
uintptr(unsafe.Pointer(w)),
)
if int(res) == -1 {
return 0, err
}
return int(w.Col), nil
}
var oldState syscall.Termios
func lockEcho() (err error) {
fd := tty.Fd()
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
err = fmt.Errorf("Can't get terminal settings: %v", e)
return
}
newState := oldState
newState.Lflag &^= syscall.ECHO
newState.Lflag |= syscall.ICANON | syscall.ISIG
newState.Iflag |= syscall.ICRNL
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); e != 0 {
err = fmt.Errorf("Can't set terminal settings: %v", e)
return
}
return
}
func unlockEcho() (err error) {
fd := tty.Fd()
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
err = fmt.Errorf("Can't set terminal settings")
}
return
}

115
vendor/github.com/cheggaaa/pb/v3/util.go generated vendored Normal file
View File

@@ -0,0 +1,115 @@
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)
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 {
w -= rw
buf.WriteRune(r)
} else {
break
}
}
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
}

20
vendor/github.com/gookit/color/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,20 @@
*.log
*.swp
.idea
*.patch
### 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
.DS_Store
app
demo

21
vendor/github.com/gookit/color/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,21 @@
language: go
env:
GO111MODULE: on
go:
# - '1.9'
# - '1.10'
- '1.11'
- '1.12'
- '1.13'
- '1.14'
- '1.15'
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
# gofmt -w ./
# - go test -v -cover
- $HOME/gopath/bin/goveralls -v -service=travis-ci

20
vendor/github.com/gookit/color/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2016 inhere
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.

422
vendor/github.com/gookit/color/README.md generated vendored Normal file
View File

@@ -0,0 +1,422 @@
# CLI Color
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/color?style=flat-square)
[![Actions Status](https://github.com/gookit/color/workflows/action-tests/badge.svg)](https://github.com/gookit/color/actions)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/51b28c5f7ffe4cc2b0f12ecf25ed247f)](https://app.codacy.com/app/inhere/color)
[![GoDoc](https://godoc.org/github.com/gookit/color?status.svg)](https://pkg.go.dev/github.com/gookit/color?tab=overview)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/color)](https://github.com/gookit/color)
[![Build Status](https://travis-ci.org/gookit/color.svg?branch=master)](https://travis-ci.org/gookit/color)
[![Coverage Status](https://coveralls.io/repos/github/gookit/color/badge.svg?branch=master)](https://coveralls.io/github/gookit/color?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/gookit/color)](https://goreportcard.com/report/github.com/gookit/color)
A command-line color library with true color support, universal API methods and Windows support.
> **[中文说明](README.zh-CN.md)**
Basic color preview:
![basic-color](_examples/images/basic-color2.png)
Now, 256 colors and RGB colors have also been supported to work in Windows CMD and PowerShell:
![color-on-cmd-pwsh](_examples/images/color-on-cmd-pwsh.jpg)
## Features
- Simple to use, zero dependencies
- Supports rich color output: 16-color, 256-color, true color (24-bit, RGB)
- 16-color output is the most commonly used and most widely supported, working on any Windows version
- Since `v1.2.4` **the 256-color, true color (24-bit) support windows CMD and PowerShell**
- See [this gist](https://gist.github.com/XVilka/8346728) for information on true color support
- Generic API methods: `Print`, `Printf`, `Println`, `Sprint`, `Sprintf`
- Supports HTML tag-style color rendering, such as `<green>message</>`. Support working on windows `cmd` `powerShell`
- Basic colors: `Bold`, `Black`, `White`, `Gray`, `Red`, `Green`, `Yellow`, `Blue`, `Magenta`, `Cyan`
- Additional styles: `Info`, `Note`, `Light`, `Error`, `Danger`, `Notice`, `Success`, `Comment`, `Primary`, `Warning`, `Question`, `Secondary`
## GoDoc
- [godoc for gopkg](https://pkg.go.dev/gopkg.in/gookit/color.v1)
- [godoc for github](https://pkg.go.dev/github.com/gookit/color)
## Install
```bash
go get github.com/gookit/color
```
## Quick start
```go
package main
import (
"fmt"
"github.com/gookit/color"
)
func main() {
// quick use like fmt.Print*
color.Red.Println("Simple to use color")
color.Green.Print("Simple to use color\n")
color.Cyan.Printf("Simple to use %s\n", "color")
color.Yellow.Printf("Simple to use %s\n", "color")
// use like func
red := color.FgRed.Render
green := color.FgGreen.Render
fmt.Printf("%s line %s library\n", red("Command"), green("color"))
// custom color
color.New(color.FgWhite, color.BgBlack).Println("custom color style")
// can also:
color.Style{color.FgCyan, color.OpBold}.Println("custom color style")
// internal theme/style:
color.Info.Tips("message")
color.Info.Prompt("message")
color.Info.Println("message")
color.Warn.Println("message")
color.Error.Println("message")
// use style tag
color.Print("<suc>he</><comment>llo</>, <cyan>wel</><red>come</>\n")
// apply a style tag
color.Tag("info").Println("info style text")
// prompt message
color.Info.Prompt("prompt style message")
color.Warn.Prompt("prompt style message")
// tips message
color.Info.Tips("tips style message")
color.Warn.Tips("tips style message")
}
```
Run demo: `go run ./_examples/demo.go`
![colored-out](_examples/images/color-demo.jpg)
## Custom Build Color
```go
// Only use foreground color
color.FgCyan.Printf("Simple to use %s\n", "color")
// Only use background color
color.BgRed.Printf("Simple to use %s\n", "color")
// Full custom: foreground, background, option
myStyle := color.New(color.FgWhite, color.BgBlack, color.OpBold)
myStyle.Println("custom color style")
// can also:
color.Style{color.FgCyan, color.OpBold}.Println("custom color style")
```
custom set console settings:
```go
// set console color
color.Set(color.FgCyan)
// print message
fmt.Print("message")
// reset console settings
color.Reset()
```
## Basic Color
Supported on any Windows version.
- `color.Bold`
- `color.Black`
- `color.White`
- `color.Gray`
- `color.Red`
- `color.Green`
- `color.Yellow`
- `color.Blue`
- `color.Magenta`
- `color.Cyan`
```go
color.Bold.Println("bold message")
color.Yellow.Println("yellow message")
```
Run demo: `go run ./_examples/basiccolor.go`
![basic-color](_examples/images/basic-color.png)
## Additional styles
Supported on any Windows version.
- `color.Info`
- `color.Note`
- `color.Warn`
- `color.Light`
- `color.Error`
- `color.Danger`
- `color.Debug`
- `color.Notice`
- `color.Success`
- `color.Comment`
- `color.Primary`
- `color.Question`
- `color.Secondary`
### Basic Style
print message use defined style:
```go
color.Info.Println("Info message")
color.Note.Println("Note message")
color.Notice.Println("Notice message")
color.Error.Println("Error message")
color.Danger.Println("Danger message")
color.Warn.Println("Warn message")
color.Debug.Println("Debug message")
color.Primary.Println("Primary message")
color.Question.Println("Question message")
color.Secondary.Println("Secondary message")
```
Run demo: `go run ./_examples/theme_basic.go`
![theme-basic](_examples/images/theme-basic.png)
### Tips Style
```go
color.Info.Tips("Info tips message")
color.Note.Tips("Note tips message")
color.Notice.Tips("Notice tips message")
color.Error.Tips("Error tips message")
color.Danger.Tips("Danger tips message")
color.Warn.Tips("Warn tips message")
color.Debug.Tips("Debug tips message")
color.Primary.Tips("Primary tips message")
color.Question.Tips("Question tips message")
color.Secondary.Tips("Secondary tips message")
```
Run demo: `go run ./_examples/theme_tips.go`
![theme-tips](_examples/images/theme-tips.png)
### Prompt Style
```go
color.Info.Prompt("Info prompt message")
color.Note.Prompt("Note prompt message")
color.Notice.Prompt("Notice prompt message")
color.Error.Prompt("Error prompt message")
color.Danger.Prompt("Danger prompt message")
color.Warn.Prompt("Warn prompt message")
color.Debug.Prompt("Debug prompt message")
color.Primary.Prompt("Primary prompt message")
color.Question.Prompt("Question prompt message")
color.Secondary.Prompt("Secondary prompt message")
```
Run demo: `go run ./_examples/theme_prompt.go`
![theme-prompt](_examples/images/theme-prompt.png)
### Block Style
```go
color.Info.Block("Info block message")
color.Note.Block("Note block message")
color.Notice.Block("Notice block message")
color.Error.Block("Error block message")
color.Danger.Block("Danger block message")
color.Warn.Block("Warn block message")
color.Debug.Block("Debug block message")
color.Primary.Block("Primary block message")
color.Question.Block("Question block message")
color.Secondary.Block("Secondary block message")
```
Run demo: `go run ./_examples/theme_block.go`
![theme-block](_examples/images/theme-block.png)
## HTML-like tag usage
**Supported** on Windows `cmd.exe` `PowerShell` .
```go
// use style tag
color.Print("<suc>he</><comment>llo</>, <cyan>wel</><red>come</>")
color.Println("<suc>hello</>")
color.Println("<error>hello</>")
color.Println("<warning>hello</>")
// custom color attributes
color.Print("<fg=yellow;bg=black;op=underscore;>hello, welcome</>\n")
```
- `color.Tag`
```go
// set a style tag
color.Tag("info").Print("info style text")
color.Tag("info").Printf("%s style text", "info")
color.Tag("info").Println("info style text")
```
Run demo: `go run ./_examples/colortag.go`
![color-tags](_examples/images/color-tags.png)
## 256-color usage
> 256 colors support Windows CMD, PowerShell environment after `v1.2.4`
### Set the foreground or background color
- `color.C256(val uint8, isBg ...bool) Color256`
```go
c := color.C256(132) // fg color
c.Println("message")
c.Printf("format %s", "message")
c := color.C256(132, true) // bg color
c.Println("message")
c.Printf("format %s", "message")
```
### Use a 256-color style
Can be used to set foreground and background colors at the same time.
- `color.S256(fgAndBg ...uint8) *Style256`
```go
s := color.S256(32, 203)
s.Println("message")
s.Printf("format %s", "message")
```
Run demo: `go run ./_examples/color256.go`
![color-tags](_examples/images/color-256.png)
## Use RGB color
> RGB colors support Windows `CMD`, `PowerShell` environment after `v1.2.4`
**Preview:**
> Run demo: `Run demo: go run ./_examples/color_rgb.go`
![color-rgb](_examples/images/color-rgb.png)
example:
```go
color.RGB(30, 144, 255).Println("message. use RGB number")
color.HEX("#1976D2").Println("blue-darken")
color.HEX("#D50000", true).Println("red-accent. use HEX style")
color.RGBStyleFromString("213,0,0").Println("red-accent. use RGB number")
color.HEXStyle("eee", "D50000").Println("deep-purple color")
```
### Set the foreground or background color
- `color.RGB(r, g, b uint8, isBg ...bool) RGBColor`
```go
c := color.RGB(30,144,255) // fg color
c.Println("message")
c.Printf("format %s", "message")
c := color.RGB(30,144,255, true) // bg color
c.Println("message")
c.Printf("format %s", "message")
```
Create a style from an hexadecimal color string:
- `color.HEX(hex string, isBg ...bool) RGBColor`
```go
c := color.HEX("ccc") // can also: "cccccc" "#cccccc"
c.Println("message")
c.Printf("format %s", "message")
c = color.HEX("aabbcc", true) // as bg color
c.Println("message")
c.Printf("format %s", "message")
```
### Use an RGB color style
Can be used to set the foreground and background colors at the same time.
- `color.NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle`
```go
s := color.NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23))
s.Println("message")
s.Printf("format %s", "message")
```
Create a style from an hexadecimal color string:
- `color.HEXStyle(fg string, bg ...string) *RGBStyle`
```go
s := color.HEXStyle("11aa23", "eee")
s.Println("message")
s.Printf("format %s", "message")
```
## Func refer
there are some useful functions reference
- `Disable()` disable color render
- `SetOutput(io.Writer)` custom set the colored text output writer
- `ForceOpenColor()` force open color render
- `ClearCode(str string) string` Use for clear color codes
- `ClearTag(s string) string` clear all color html-tag for a string
- `IsConsole(w io.Writer)` Determine whether w is one of stderr, stdout, stdin
- `HexToRgb(hex string) (rgb []int)` Convert hex color string to RGB numbers
- `RgbToHex(rgb []int) string` Convert RGB to hex code
## Gookit packages
- [gookit/ini](https://github.com/gookit/ini) Go config management, use INI files
- [gookit/rux](https://github.com/gookit/rux) Simple and fast request router for golang HTTP
- [gookit/gcli](https://github.com/gookit/gcli) build CLI application, tool library, running CLI commands
- [gookit/event](https://github.com/gookit/event) Lightweight event manager and dispatcher implements by Go
- [gookit/cache](https://github.com/gookit/cache) Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
- [gookit/config](https://github.com/gookit/config) Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
- [gookit/color](https://github.com/gookit/color) A command-line color library with true color support, universal API methods and Windows support
- [gookit/filter](https://github.com/gookit/filter) Provide filtering, sanitizing, and conversion of golang data
- [gookit/validate](https://github.com/gookit/validate) Use for data validation and filtering. support Map, Struct, Form data
- [gookit/goutil](https://github.com/gookit/goutil) Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
- More please see https://github.com/gookit
## See also
- [`issue9/term`](https://github.com/issue9/term)
- [`beego/bee`](https://github.com/beego/bee)
- [`inhere/console`](https://github.com/inhere/php-console)
- [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code)
## License
[MIT](/LICENSE)

392
vendor/github.com/gookit/color/README.zh-CN.md generated vendored Normal file
View File

@@ -0,0 +1,392 @@
# CLI Color
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/color?style=flat-square)
[![Actions Status](https://github.com/gookit/color/workflows/action-tests/badge.svg)](https://github.com/gookit/color/actions)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/51b28c5f7ffe4cc2b0f12ecf25ed247f)](https://app.codacy.com/app/inhere/color)
[![GoDoc](https://godoc.org/github.com/gookit/color?status.svg)](https://pkg.go.dev/github.com/gookit/color?tab=overview)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/color)](https://github.com/gookit/color)
[![Build Status](https://travis-ci.org/gookit/color.svg?branch=master)](https://travis-ci.org/gookit/color)
[![Coverage Status](https://coveralls.io/repos/github/gookit/color/badge.svg?branch=master)](https://coveralls.io/github/gookit/color?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/gookit/color)](https://goreportcard.com/report/github.com/gookit/color)
Golang下的命令行色彩使用库, 拥有丰富的色彩渲染输出通用的API方法兼容Windows系统
> **[EN README](README.md)**
基本颜色预览:
![basic-color](_examples/images/basic-color2.png)
现在256色和RGB色彩也已经支持windows CMD和PowerShell中工作
![color-on-cmd-pwsh](_examples/images/color-on-cmd-pwsh.jpg)
## 功能特色
- 使用简单方便,无其他依赖
- 支持丰富的颜色输出, 16色(4bit)256色(8bit)RGB色彩(24bit, RGB)
- 16色(4bit)是最常用和支持最广的支持Windows `cmd.exe`
-`v1.2.4`**256色(8bit)RGB色彩(24bit)均支持windows CMD和PowerShell终端**
- 请查看 [this gist](https://gist.github.com/XVilka/8346728) 了解支持RGB色彩的终端
- 通用的API方法`Print` `Printf` `Println` `Sprint` `Sprintf`
- 同时支持html标签式的颜色渲染. eg: `<green>message</>`
- 基础色彩: `Bold` `Black` `White` `Gray` `Red` `Green` `Yellow` `Blue` `Magenta` `Cyan`
- 扩展风格: `Info` `Note` `Light` `Error` `Danger` `Notice` `Success` `Comment` `Primary` `Warning` `Question` `Secondary`
- 支持Linux、Mac同时兼容Windows系统环境
## GoDoc
- [godoc for gopkg](https://pkg.go.dev/gopkg.in/gookit/color.v1)
- [godoc for github](https://pkg.go.dev/github.com/gookit/color)
## 安装
```bash
go get github.com/gookit/color
```
## 快速开始
如下,引入当前包就可以快速的使用
```go
package main
import (
"fmt"
"github.com/gookit/color"
)
func main() {
// 简单快速的使用,跟 fmt.Print* 类似
color.Red.Println("Simple to use color")
color.Green.Print("Simple to use color\n")
color.Cyan.Printf("Simple to use %s\n", "color")
color.Yellow.Printf("Simple to use %s\n", "color")
// use like func
red := color.FgRed.Render
green := color.FgGreen.Render
fmt.Printf("%s line %s library\n", red("Command"), green("color"))
// 自定义颜色
color.New(color.FgWhite, color.BgBlack).Println("custom color style")
// 也可以:
color.Style{color.FgCyan, color.OpBold}.Println("custom color style")
// internal style:
color.Info.Println("message")
color.Warn.Println("message")
color.Error.Println("message")
// 使用颜色标签
color.Print("<suc>he</><comment>llo</>, <cyan>wel</><red>come</>\n")
// apply a style tag
color.Tag("info").Println("info style text")
// prompt message
color.Info.Prompt("prompt style message")
color.Warn.Prompt("prompt style message")
// tips message
color.Info.Tips("tips style message")
color.Warn.Tips("tips style message")
}
```
> 运行 demo: `go run ./_examples/demo.go`
![colored-out](_examples/images/color-demo.jpg)
## 构建风格
```go
// 仅设置前景色
color.FgCyan.Printf("Simple to use %s\n", "color")
// 仅设置背景色
color.BgRed.Printf("Simple to use %s\n", "color")
// 完全自定义: 前景色 背景色 选项
style := color.New(color.FgWhite, color.BgBlack, color.OpBold)
style.Println("custom color style")
// 也可以:
color.Style{color.FgCyan, color.OpBold}.Println("custom color style")
```
直接设置控制台属性:
```go
// 设置console颜色
color.Set(color.FgCyan)
// 输出信息
fmt.Print("message")
// 重置console颜色
color.Reset()
```
> 当然color已经内置丰富的色彩风格支持
## 基础颜色方法
> 支持在windows `cmd.exe` 使用
- `color.Bold`
- `color.Black`
- `color.White`
- `color.Gray`
- `color.Red`
- `color.Green`
- `color.Yellow`
- `color.Blue`
- `color.Magenta`
- `color.Cyan`
```go
color.Bold.Println("bold message")
color.Yellow.Println("yellow message")
```
> 运行demo: `go run ./_examples/basiccolor.go`
![basic-color](_examples/images/basic-color.png)
## 扩展风格方法
> 支持在windows `cmd.exe` 使用
- `color.Info`
- `color.Note`
- `color.Light`
- `color.Error`
- `color.Danger`
- `color.Notice`
- `color.Success`
- `color.Comment`
- `color.Primary`
- `color.Warning`
- `color.Question`
- `color.Secondary`
### 基础风格
```go
// print message
color.Info.Println("Info message")
color.Success.Println("Success message")
```
Run demo: `go run ./_examples/theme_basic.go`
![theme-basic](_examples/images/theme-basic.png)
### 简约提示风格
```go
color.Info.Tips("tips style message")
color.Warn.Tips("tips style message")
```
Run demo: `go run ./_examples/theme_tips.go`
![theme-tips](_examples/images/theme-tips.png)
### 着重提示风格
```go
color.Info.Prompt("prompt style message")
color.Warn.Prompt("prompt style message")
```
Run demo: `go run ./_examples/theme_prompt.go`
![theme-prompt](_examples/images/theme-prompt.png)
### 强调提示风格
```go
color.Info.Block("prompt style message")
color.Warn.Block("prompt style message")
```
Run demo: `go run ./_examples/theme_block.go`
![theme-block](_examples/images/theme-block.png)
### 使用颜色标签
> **支持** 在windows `cmd.exe` `PowerShell` 使用
使用内置的颜色标签,可以非常方便简单的构建自己需要的任何格式
```go
// 使用内置的 color tag
color.Print("<suc>he</><comment>llo</>, <cyan>wel</><red>come</>")
color.Println("<suc>hello</>")
color.Println("<error>hello</>")
color.Println("<warning>hello</>")
// 自定义颜色属性
color.Print("<fg=yellow;bg=black;op=underscore;>hello, welcome</>\n")
```
- 使用 `color.Tag`
给后面输出的文本信息加上给定的颜色风格标签
```go
// set a style tag
color.Tag("info").Print("info style text")
color.Tag("info").Printf("%s style text", "info")
color.Tag("info").Println("info style text")
```
> 运行 demo: `go run ./_examples/colortag.go`
![color-tags](_examples/images/color-tags.png)
## 256色使用
> 256色彩在 `v1.2.4` 后支持Windows CMD,PowerShell 环境
### 使用前景或后景色
- `color.C256(val uint8, isBg ...bool) Color256`
```go
c := color.C256(132) // fg color
c.Println("message")
c.Printf("format %s", "message")
c := color.C256(132, true) // bg color
c.Println("message")
c.Printf("format %s", "message")
```
### 使用风格
> 可同时设置前景和背景色
- `color.S256(fgAndBg ...uint8) *Style256`
```go
s := color.S256(32, 203)
s.Println("message")
s.Printf("format %s", "message")
```
> 运行 demo: `go run ./_examples/color256.go`
![color-tags](_examples/images/color-256.png)
## RGB色彩使用
> RGB色彩在 `v1.2.4` 后支持 Windows `CMD`, `PowerShell` 环境
**效果预览:**
> 运行 demo: `Run demo: go run ./_examples/color_rgb.go`
![color-rgb](_examples/images/color-rgb.png)
代码示例:
```go
color.RGB(30, 144, 255).Println("message. use RGB number")
color.HEX("#1976D2").Println("blue-darken")
color.HEX("#D50000", true).Println("red-accent. use HEX style")
color.RGBStyleFromString("213,0,0").Println("red-accent. use RGB number")
color.HEXStyle("eee", "D50000").Println("deep-purple color")
```
### 使用前景或后景色
- `color.RGB(r, g, b uint8, isBg ...bool) RGBColor`
```go
c := color.RGB(30,144,255) // fg color
c.Println("message")
c.Printf("format %s", "message")
c := color.RGB(30,144,255, true) // bg color
c.Println("message")
c.Printf("format %s", "message")
```
- `color.HEX(hex string, isBg ...bool) RGBColor` 从16进制颜色创建
```go
c := color.HEX("ccc") // 也可以写为: "cccccc" "#cccccc"
c.Println("message")
c.Printf("format %s", "message")
c = color.HEX("aabbcc", true) // as bg color
c.Println("message")
c.Printf("format %s", "message")
```
### 使用风格
> 可同时设置前景和背景色
- `color.NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle`
```go
s := color.NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23))
s.Println("message")
s.Printf("format %s", "message")
```
- `color.HEXStyle(fg string, bg ...string) *RGBStyle` 从16进制颜色创建
```go
s := color.HEXStyle("11aa23", "eee")
s.Println("message")
s.Printf("format %s", "message")
```
## 方法参考
一些有用的工具方法参考
- `Disable()` disable color render
- `SetOutput(io.Writer)` custom set the colored text output writer
- `ForceOpenColor()` force open color render
- `ClearCode(str string) string` Use for clear color codes
- `ClearTag(s string) string` clear all color html-tag for a string
- `IsConsole(w io.Writer)` Determine whether w is one of stderr, stdout, stdin
- `HexToRgb(hex string) (rgb []int)` Convert hex color string to RGB numbers
- `RgbToHex(rgb []int) string` Convert RGB to hex code
## Gookit 工具包
- [gookit/ini](https://github.com/gookit/ini) INI配置读取管理支持多文件加载数据覆盖合并, 解析ENV变量, 解析变量引用
- [gookit/rux](https://github.com/gookit/rux) Simple and fast request router for golang HTTP
- [gookit/gcli](https://github.com/gookit/gcli) Go的命令行应用工具库运行CLI命令支持命令行色彩用户交互进度显示数据格式化显示
- [gookit/event](https://github.com/gookit/event) Go实现的轻量级的事件管理、调度程序库, 支持设置监听器的优先级, 支持对一组事件进行监听
- [gookit/cache](https://github.com/gookit/cache) 通用的缓存使用包装库通过包装各种常用的驱动来提供统一的使用API
- [gookit/config](https://github.com/gookit/config) Go应用配置管理支持多种格式JSON, YAML, TOML, INI, HCL, ENV, Flags多文件加载远程文件加载数据合并
- [gookit/color](https://github.com/gookit/color) CLI 控制台颜色渲染工具库, 拥有简洁的使用API支持16色256色RGB色彩渲染输出
- [gookit/filter](https://github.com/gookit/filter) 提供对Golang数据的过滤净化转换
- [gookit/validate](https://github.com/gookit/validate) Go通用的数据验证与过滤库使用简单内置大部分常用验证、过滤器
- [gookit/goutil](https://github.com/gookit/goutil) Go 的一些工具函数,格式化,特殊处理,常用信息获取等
- 更多请查看 https://github.com/gookit
## 参考项目
- `issue9/term` https://github.com/issue9/term
- `beego/bee` https://github.com/beego/bee
- `inhere/console` https://github/inhere/php-console
- [ANSI转义序列](https://zh.wikipedia.org/wiki/ANSI转义序列)
- [Standard ANSI color map](https://conemu.github.io/en/AnsiEscapeCodes.html#Standard_ANSI_color_map)
## License
MIT

272
vendor/github.com/gookit/color/color.go generated vendored Normal file
View File

@@ -0,0 +1,272 @@
/*
Package color is Command line color library.
Support rich color rendering output, universal API method, compatible with Windows system
Source code and other details for the project are available at GitHub:
https://github.com/gookit/color
More usage please see README and tests.
*/
package color
import (
"fmt"
"io"
"os"
"regexp"
)
// console color mode
// const (
// ModeNormal = iota
// Mode256 // 8 bite
// ModeRGB // 24 bite
// ModeGrayscale
// )
// color render templates
// ESC 操作的表示:
// "\033"(Octal 8进制) = "\x1b"(Hexadecimal 16进制) = 27 (10进制)
const (
SettingTpl = "\x1b[%sm"
FullColorTpl = "\x1b[%sm%s\x1b[0m"
)
// ResetSet Close all properties.
const ResetSet = "\x1b[0m"
// CodeExpr regex to clear color codes eg "\033[1;36mText\x1b[0m"
const CodeExpr = `\033\[[\d;?]+m`
var (
// Enable switch color render and display
Enable = true
// RenderTag render HTML tag on call color.Xprint, color.PrintX
RenderTag = true
// errors on windows render OR print to io.Writer
errors []error
// output the default io.Writer message print
output io.Writer = os.Stdout
// mark current env, It's like in `cmd.exe`
// if not in windows, is's always is False.
isLikeInCmd bool
// match color codes
codeRegex = regexp.MustCompile(CodeExpr)
// mark current env is support color.
// Always: isLikeInCmd != isSupportColor
isSupportColor = IsSupportColor()
)
/*************************************************************
* global settings
*************************************************************/
// Set set console color attributes
func Set(colors ...Color) (int, error) {
if !Enable { // not enable
return 0, nil
}
// on windows cmd.exe
// if isLikeInCmd {
// return winSet(colors...)
// }
return fmt.Printf(SettingTpl, colors2code(colors...))
}
// Reset reset console color attributes
func Reset() (int, error) {
if !Enable { // not enable
return 0, nil
}
// on windows cmd.exe
// if isLikeInCmd {
// return winReset()
// }
return fmt.Print(ResetSet)
}
// Disable disable color output
func Disable() bool {
oldVal := Enable
Enable = false
return oldVal
}
// NotRenderTag on call color.Xprint, color.PrintX
func NotRenderTag() {
RenderTag = false
}
// SetOutput set default colored text output
func SetOutput(w io.Writer) {
output = w
}
// ResetOutput reset output
func ResetOutput() {
output = os.Stdout
}
// ResetOptions reset all package option setting
func ResetOptions() {
RenderTag = true
Enable = true
output = os.Stdout
}
// ForceColor force open color render
func ForceColor() bool {
return ForceOpenColor()
}
// ForceOpenColor force open color render
func ForceOpenColor() bool {
oldVal := isSupportColor
isSupportColor = true
return oldVal
}
// IsLikeInCmd check result
func IsLikeInCmd() bool {
return isLikeInCmd
}
// GetErrors info
func GetErrors() []error {
return errors
}
/*************************************************************
* render color code
*************************************************************/
// RenderCode render message by color code.
// Usage:
// msg := RenderCode("3;32;45", "some", "message")
func RenderCode(code string, args ...interface{}) string {
var message string
if ln := len(args); ln == 0 {
return ""
}
message = fmt.Sprint(args...)
if len(code) == 0 {
return message
}
// disabled OR not support color
if !Enable || !isSupportColor {
return ClearCode(message)
}
return fmt.Sprintf(FullColorTpl, code, message)
}
// RenderWithSpaces Render code with spaces.
// If the number of args is > 1, a space will be added between the args
func RenderWithSpaces(code string, args ...interface{}) string {
message := formatArgsForPrintln(args)
if len(code) == 0 {
return message
}
// disabled OR not support color
if !Enable || !isSupportColor {
return ClearCode(message)
}
return fmt.Sprintf(FullColorTpl, code, message)
}
// RenderString render a string with color code.
// Usage:
// msg := RenderString("3;32;45", "a message")
func RenderString(code string, str string) string {
if len(code) == 0 || str == "" {
return str
}
// disabled OR not support color
if !Enable || !isSupportColor {
return ClearCode(str)
}
return fmt.Sprintf(FullColorTpl, code, str)
}
// ClearCode clear color codes.
// eg:
// "\033[36;1mText\x1b[0m" -> "Text"
func ClearCode(str string) string {
return codeRegex.ReplaceAllString(str, "")
}
/*************************************************************
* colored message Printer
*************************************************************/
// PrinterFace interface
type PrinterFace interface {
fmt.Stringer
Sprint(a ...interface{}) string
Sprintf(format string, a ...interface{}) string
Print(a ...interface{})
Printf(format string, a ...interface{})
Println(a ...interface{})
}
// Printer a generic color message printer.
// Usage:
// p := &Printer{"32;45;3"}
// p.Print("message")
type Printer struct {
// ColorCode color code string. eg "32;45;3"
ColorCode string
}
// NewPrinter instance
func NewPrinter(colorCode string) *Printer {
return &Printer{colorCode}
}
// String returns color code string. eg: "32;45;3"
func (p *Printer) String() string {
// panic("implement me")
return p.ColorCode
}
// Sprint returns rendering colored messages
func (p *Printer) Sprint(a ...interface{}) string {
return RenderCode(p.String(), a...)
}
// Sprintf returns format and rendering colored messages
func (p *Printer) Sprintf(format string, a ...interface{}) string {
return RenderString(p.String(), fmt.Sprintf(format, a...))
}
// Print rendering colored messages
func (p *Printer) Print(a ...interface{}) {
doPrintV2(p.String(), fmt.Sprint(a...))
}
// Printf format and rendering colored messages
func (p *Printer) Printf(format string, a ...interface{}) {
doPrintV2(p.String(), fmt.Sprintf(format, a...))
}
// Println rendering colored messages with newline
func (p *Printer) Println(a ...interface{}) {
doPrintlnV2(p.ColorCode, a)
}
// IsEmpty color code
func (p *Printer) IsEmpty() bool {
return p.ColorCode == ""
}

300
vendor/github.com/gookit/color/color_16.go generated vendored Normal file
View File

@@ -0,0 +1,300 @@
package color
import (
"fmt"
"strings"
)
// Color Color16, 16 color value type
// 3(2^3=8) OR 4(2^4=16) bite color.
type Color uint8
/*************************************************************
* Basic 16 color definition
*************************************************************/
// Foreground colors. basic foreground colors 30 - 37
const (
FgBlack Color = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta // 品红
FgCyan // 青色
FgWhite
// FgDefault revert default FG
FgDefault Color = 39
)
// Extra foreground color 90 - 97(非标准)
const (
FgDarkGray Color = iota + 90 // 亮黑(灰)
FgLightRed
FgLightGreen
FgLightYellow
FgLightBlue
FgLightMagenta
FgLightCyan
FgLightWhite
// FgGray is alias of FgDarkGray
FgGray Color = 90 // 亮黑(灰)
)
// Background colors. basic background colors 40 - 47
const (
BgBlack Color = iota + 40
BgRed
BgGreen
BgYellow // BgBrown like yellow
BgBlue
BgMagenta
BgCyan
BgWhite
// BgDefault revert default BG
BgDefault Color = 49
)
// Extra background color 100 - 107(非标准)
const (
BgDarkGray Color = iota + 100
BgLightRed
BgLightGreen
BgLightYellow
BgLightBlue
BgLightMagenta
BgLightCyan
BgLightWhite
// BgGray is alias of BgDarkGray
BgGray Color = 100
)
// Option settings
const (
OpReset Color = iota // 0 重置所有设置
OpBold // 1 加粗
OpFuzzy // 2 模糊(不是所有的终端仿真器都支持)
OpItalic // 3 斜体(不是所有的终端仿真器都支持)
OpUnderscore // 4 下划线
OpBlink // 5 闪烁
OpFastBlink // 5 快速闪烁(未广泛支持)
OpReverse // 7 颠倒的 交换背景色与前景色
OpConcealed // 8 隐匿的
OpStrikethrough // 9 删除的,删除线(未广泛支持)
)
// There are basic and light foreground color aliases
const (
Red = FgRed
Cyan = FgCyan
Gray = FgDarkGray // is light Black
Blue = FgBlue
Black = FgBlack
Green = FgGreen
White = FgWhite
Yellow = FgYellow
Magenta = FgMagenta
// special
Bold = OpBold
Normal = FgDefault
// extra light
LightRed = FgLightRed
LightCyan = FgLightCyan
LightBlue = FgLightBlue
LightGreen = FgLightGreen
LightWhite = FgLightWhite
LightYellow = FgLightYellow
LightMagenta = FgLightMagenta
)
/*************************************************************
* Color render methods
*************************************************************/
// Text render a text message
func (c Color) Text(message string) string {
return RenderString(c.String(), message)
}
// Render messages by color setting
// Usage:
// green := color.FgGreen.Render
// fmt.Println(green("message"))
func (c Color) Render(a ...interface{}) string {
return RenderCode(c.String(), a...)
}
// Renderln messages by color setting.
// like Println, will add spaces for each argument
// Usage:
// green := color.FgGreen.Renderln
// fmt.Println(green("message"))
func (c Color) Renderln(a ...interface{}) string {
return RenderWithSpaces(c.String(), a...)
}
// Sprint render messages by color setting. is alias of the Render()
func (c Color) Sprint(a ...interface{}) string {
return RenderCode(c.String(), a...)
}
// Sprintf format and render message.
// Usage:
// green := color.Green.Sprintf
// colored := green("message")
func (c Color) Sprintf(format string, args ...interface{}) string {
return RenderString(c.String(), fmt.Sprintf(format, args...))
}
// Print messages.
// Usage:
// color.Green.Print("message")
// OR:
// green := color.FgGreen.Print
// green("message")
func (c Color) Print(args ...interface{}) {
doPrintV2(c.Code(), fmt.Sprint(args...))
}
// Printf format and print messages.
// Usage:
// color.Cyan.Printf("string %s", "arg0")
func (c Color) Printf(format string, a ...interface{}) {
doPrintV2(c.Code(), fmt.Sprintf(format, a...))
}
// Println messages with new line
func (c Color) Println(a ...interface{}) {
doPrintlnV2(c.String(), a)
}
// Light current color. eg: 36(FgCyan) -> 96(FgLightCyan).
// Usage:
// lightCyan := Cyan.Light()
// lightCyan.Print("message")
func (c Color) Light() Color {
val := int(c)
if val >= 30 && val <= 47 {
return Color(uint8(c) + 60)
}
// don't change
return c
}
// Darken current color. eg. 96(FgLightCyan) -> 36(FgCyan)
// Usage:
// cyan := LightCyan.Darken()
// cyan.Print("message")
func (c Color) Darken() Color {
val := int(c)
if val >= 90 && val <= 107 {
return Color(uint8(c) - 60)
}
// don't change
return c
}
// Code convert to code string. eg "35"
func (c Color) Code() string {
return fmt.Sprintf("%d", c)
}
// String convert to code string. eg "35"
func (c Color) String() string {
return fmt.Sprintf("%d", c)
}
// IsValid color value
func (c Color) IsValid() bool {
return c < 107
}
/*************************************************************
* basic color maps
*************************************************************/
// FgColors foreground colors map
var FgColors = map[string]Color{
"black": FgBlack,
"red": FgRed,
"green": FgGreen,
"yellow": FgYellow,
"blue": FgBlue,
"magenta": FgMagenta,
"cyan": FgCyan,
"white": FgWhite,
"default": FgDefault,
}
// BgColors background colors map
var BgColors = map[string]Color{
"black": BgBlack,
"red": BgRed,
"green": BgGreen,
"yellow": BgYellow,
"blue": BgBlue,
"magenta": BgMagenta,
"cyan": BgCyan,
"white": BgWhite,
"default": BgDefault,
}
// ExFgColors extra foreground colors map
var ExFgColors = map[string]Color{
"darkGray": FgDarkGray,
"lightRed": FgLightRed,
"lightGreen": FgLightGreen,
"lightYellow": FgLightYellow,
"lightBlue": FgLightBlue,
"lightMagenta": FgLightMagenta,
"lightCyan": FgLightCyan,
"lightWhite": FgLightWhite,
}
// ExBgColors extra background colors map
var ExBgColors = map[string]Color{
"darkGray": BgDarkGray,
"lightRed": BgLightRed,
"lightGreen": BgLightGreen,
"lightYellow": BgLightYellow,
"lightBlue": BgLightBlue,
"lightMagenta": BgLightMagenta,
"lightCyan": BgLightCyan,
"lightWhite": BgLightWhite,
}
// Options color options map
var Options = map[string]Color{
"reset": OpReset,
"bold": OpBold,
"fuzzy": OpFuzzy,
"italic": OpItalic,
"underscore": OpUnderscore,
"blink": OpBlink,
"reverse": OpReverse,
"concealed": OpConcealed,
}
/*************************************************************
* helper methods
*************************************************************/
// convert colors to code. return like "32;45;3"
func colors2code(colors ...Color) string {
if len(colors) == 0 {
return ""
}
var codes []string
for _, color := range colors {
codes = append(codes, color.String())
}
return strings.Join(codes, ";")
}

218
vendor/github.com/gookit/color/color_256.go generated vendored Normal file
View File

@@ -0,0 +1,218 @@
package color
import (
"fmt"
"strings"
)
/*
from wikipedia, 256 color:
ESC[ … 38;5;<n> … m选择前景色
ESC[ … 48;5;<n> … m选择背景色
0- 7标准颜色同 ESC[3037m
8- 15高强度颜色同 ESC[9097m
16-2316 × 6 × 6 立方216色: 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
232-255从黑到白的24阶灰度色
*/
// tpl for 8 bit 256 color(`2^8`)
//
// format:
// ESC[ … 38;5;<n> … m // 选择前景色
// ESC[ … 48;5;<n> … m // 选择背景色
//
// example:
// fg "\x1b[38;5;242m"
// bg "\x1b[48;5;208m"
// both "\x1b[38;5;242;48;5;208m"
//
// links:
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位
const (
TplFg256 = "38;5;%d"
TplBg256 = "48;5;%d"
)
/*************************************************************
* 8bit(256) Color: Bit8Color Color256
*************************************************************/
// Color256 256 (8 bit) color, uint8 range at 0 - 255
//
// 颜色值使用10进制和16进制都可 0x98 = 152
//
// 颜色有两位uint8组成:
// 0: color value
// 1: color type, Fg=0 Bg=1
// >1: unset value
// example:
// fg color: [152, 0]
// bg color: [152, 1]
//
// NOTICE: now support 256 color on windows CMD, PowerShell
type Color256 [2]uint8
// Bit8 create a color256
func Bit8(val uint8, isBg ...bool) Color256 {
return C256(val, isBg...)
}
// C256 create a color256
func C256(val uint8, isBg ...bool) Color256 {
bc := Color256{val}
// mark is bg color
if len(isBg) > 0 && isBg[0] {
bc[1] = AsBg
}
return bc
}
// Print print message
func (c Color256) Print(a ...interface{}) {
doPrintV2(c.String(), fmt.Sprint(a...))
}
// Printf format and print message
func (c Color256) Printf(format string, a ...interface{}) {
doPrintV2(c.String(), fmt.Sprintf(format, a...))
}
// Println print message with newline
func (c Color256) Println(a ...interface{}) {
doPrintlnV2(c.String(), a)
}
// Sprint returns rendered message
func (c Color256) Sprint(a ...interface{}) string {
return RenderCode(c.String(), a...)
}
// Sprintf returns format and rendered message
func (c Color256) Sprintf(format string, a ...interface{}) string {
return RenderString(c.String(), fmt.Sprintf(format, a...))
}
// Value return color value
func (c Color256) Value() uint8 {
return c[0]
}
// String convert to color code string.
func (c Color256) String() string {
if c[1] == AsFg { // 0 is Fg
return fmt.Sprintf(TplFg256, c[0])
}
if c[1] == AsBg { // 1 is Bg
return fmt.Sprintf(TplBg256, c[0])
}
// empty
return ""
}
// IsEmpty value
func (c Color256) IsEmpty() bool {
return c[1] > 1
}
/*************************************************************
* 8bit(256) Style
*************************************************************/
// Style256 definition
//
// 前/背景色
// 都是由两位uint8组成, 第一位是色彩值;
// 第二位与Bit8Color不一样的是在这里表示是否设置了值 0 未设置 ^0 已设置
type Style256 struct {
p *Printer
// Name of the style
Name string
// fg and bg color
fg, bg Color256
}
// S256 create a color256 style
// Usage:
// s := color.S256()
// s := color.S256(132) // fg
// s := color.S256(132, 203) // fg and bg
func S256(fgAndBg ...uint8) *Style256 {
s := &Style256{}
vl := len(fgAndBg)
if vl > 0 { // with fg
s.fg = Color256{fgAndBg[0], 1}
if vl > 1 { // and with bg
s.bg = Color256{fgAndBg[1], 1}
}
}
return s
}
// Set fg and bg color value
func (s *Style256) Set(fgVal, bgVal uint8) *Style256 {
s.fg = Color256{fgVal, 1}
s.bg = Color256{bgVal, 1}
return s
}
// SetBg set bg color value
func (s *Style256) SetBg(bgVal uint8) *Style256 {
s.bg = Color256{bgVal, 1}
return s
}
// SetFg set fg color value
func (s *Style256) SetFg(fgVal uint8) *Style256 {
s.fg = Color256{fgVal, 1}
return s
}
// Print print message
func (s *Style256) Print(a ...interface{}) {
doPrintV2(s.String(), fmt.Sprint(a...))
}
// Printf format and print message
func (s *Style256) Printf(format string, a ...interface{}) {
doPrintV2(s.String(), fmt.Sprintf(format, a...))
}
// Println print message with newline
func (s *Style256) Println(a ...interface{}) {
doPrintlnV2(s.String(), a)
}
// Sprint returns rendered message
func (s *Style256) Sprint(a ...interface{}) string {
return RenderCode(s.Code(), a...)
}
// Sprintf returns format and rendered message
func (s *Style256) Sprintf(format string, a ...interface{}) string {
return RenderString(s.Code(), fmt.Sprintf(format, a...))
}
// Code convert to color code string
func (s *Style256) Code() string {
return s.String()
}
// String convert to color code string
func (s *Style256) String() string {
var ss []string
if s.fg[1] > 0 {
ss = append(ss, fmt.Sprintf(TplFg256, s.fg[0]))
}
if s.bg[1] > 0 {
ss = append(ss, fmt.Sprintf(TplBg256, s.bg[0]))
}
return strings.Join(ss, ";")
}

23
vendor/github.com/gookit/color/color_nonwin.go generated vendored Normal file
View File

@@ -0,0 +1,23 @@
// +build !windows
// The method in the file has no effect
// Only for compatibility with non-Windows systems
package color
func winSet(_ ...Color) (n int, err error) {
return
}
func winReset() (n int, err error) {
return
}
func winPrint(_ string, _ ...Color) {}
func winPrintln(_ string, _ ...Color) {}
func renderColorCodeOnCmd(_ func()) {}
// IsTerminal check currently is terminal
func IsTerminal(_ int) bool {
return true
}

301
vendor/github.com/gookit/color/color_rgb.go generated vendored Normal file
View File

@@ -0,0 +1,301 @@
package color
import (
"fmt"
"strconv"
"strings"
)
// 24 bit RGB color
// RGB:
// R 0-255 G 0-255 B 0-255
// R 00-FF G 00-FF B 00-FF (16进制)
//
// Format:
// ESC[ … 38;2;<r>;<g>;<b> … m // Select RGB foreground color
// ESC[ … 48;2;<r>;<g>;<b> … m // Choose RGB background color
//
// links:
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位
//
// example:
// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m
// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m
// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m
const (
TplFgRGB = "38;2;%d;%d;%d"
TplBgRGB = "48;2;%d;%d;%d"
)
// mark color is fg or bg.
const (
AsFg uint8 = iota
AsBg
)
/*************************************************************
* RGB Color(Bit24Color, TrueColor)
*************************************************************/
// RGBColor definition.
//
// The first to third digits represent the color value.
// The last digit represents the foreground(0), background(1), >1 is unset value
//
// Usage:
// // 0, 1, 2 is R,G,B.
// // 3rd: Fg=0, Bg=1, >1: unset value
// RGBColor{30,144,255, 0}
// RGBColor{30,144,255, 1}
//
// NOTICE: now support RGB color on windows CMD, PowerShell
type RGBColor [4]uint8
// create a empty RGBColor
var emptyRGBColor = RGBColor{3: 99}
// RGB color create.
// Usage:
// c := RGB(30,144,255)
// c := RGB(30,144,255, true)
// c.Print("message")
func RGB(r, g, b uint8, isBg ...bool) RGBColor {
rgb := RGBColor{r, g, b}
if len(isBg) > 0 && isBg[0] {
rgb[3] = AsBg
}
return rgb
}
// HEX create RGB color from a HEX color string.
// Usage:
// c := HEX("ccc") // rgb: [204 204 204]
// c := HEX("aabbcc") // rgb: [170 187 204]
// c := HEX("#aabbcc")
// c := HEX("0xaabbcc")
// c.Print("message")
func HEX(hex string, isBg ...bool) RGBColor {
if rgb := HexToRgb(hex); len(rgb) > 0 {
return RGB(uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), isBg...)
}
// mark is empty
return emptyRGBColor
}
// RGBFromString create RGB color from a string.
// Usage:
// c := RGBFromString("170,187,204")
// c.Print("message")
func RGBFromString(rgb string, isBg ...bool) RGBColor {
ss := stringToArr(rgb, ",")
if len(ss) != 3 {
return emptyRGBColor
}
var ar [3]int
for i, val := range ss {
iv, err := strconv.Atoi(val)
if err != nil {
return emptyRGBColor
}
ar[i] = iv
}
return RGB(uint8(ar[0]), uint8(ar[1]), uint8(ar[2]), isBg...)
}
// Print print message
func (c RGBColor) Print(a ...interface{}) {
doPrintV2(c.String(), fmt.Sprint(a...))
}
// Printf format and print message
func (c RGBColor) Printf(format string, a ...interface{}) {
doPrintV2(c.String(), fmt.Sprintf(format, a...))
}
// Println print message with newline
func (c RGBColor) Println(a ...interface{}) {
doPrintlnV2(c.String(), a)
}
// Sprint returns rendered message
func (c RGBColor) Sprint(a ...interface{}) string {
return RenderCode(c.String(), a...)
}
// Sprintf returns format and rendered message
func (c RGBColor) Sprintf(format string, a ...interface{}) string {
return RenderString(c.Code(), fmt.Sprintf(format, a...))
}
// Values to RGB values
func (c RGBColor) Values() []int {
return []int{int(c[0]), int(c[1]), int(c[2])}
}
// Code to color code string
func (c RGBColor) Code() string {
return c.String()
}
// String to color code string
func (c RGBColor) String() string {
if c[3] == AsFg { // 0 is Fg
return fmt.Sprintf(TplFgRGB, c[0], c[1], c[2])
}
if c[3] == AsBg { // 1 is Bg
return fmt.Sprintf(TplBgRGB, c[0], c[1], c[2])
}
// >1 is empty
return ""
}
// IsEmpty value
func (c RGBColor) IsEmpty() bool {
return c[3] > 1
}
// C256 returns the closest approximate 256 (8 bit) color
func (c RGBColor) C256() Color256 {
var isBg bool
if c[3] == 0 {
isBg = false
} else if c[3] == 1 {
isBg = true
}
return C256(rgb2short(c[0], c[1], c[2]), isBg)
}
/*************************************************************
* RGB Style
*************************************************************/
// RGBStyle definition.
//
// Foreground/Background color
// All are composed of 4 digits uint8, the first three digits are the color value;
// The last bit is different from RGBColor, here it indicates whether the value is set.
// - 1 Has been set
// - ^1 Not set
type RGBStyle struct {
// Name of the style
Name string
// fg and bg color
fg, bg RGBColor
}
// NewRGBStyle create a RGBStyle.
func NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle {
s := &RGBStyle{}
if len(bg) > 0 {
s.SetBg(bg[0])
}
return s.SetFg(fg)
}
// HEXStyle create a RGBStyle from HEX color string.
// Usage:
// s := HEXStyle("aabbcc", "eee")
// s.Print("message")
func HEXStyle(fg string, bg ...string) *RGBStyle {
s := &RGBStyle{}
if len(bg) > 0 {
s.SetBg(HEX(bg[0]))
}
if len(fg) > 0 {
s.SetFg(HEX(fg))
}
return s
}
// RGBStyleFromString create a RGBStyle from color value string.
// Usage:
// s := RGBStyleFromString("170,187,204", "70,87,4")
// s.Print("message")
func RGBStyleFromString(fg string, bg ...string) *RGBStyle {
s := &RGBStyle{}
if len(bg) > 0 {
s.SetBg(RGBFromString(bg[0]))
}
return s.SetFg(RGBFromString(fg))
}
// Set fg and bg color
func (s *RGBStyle) Set(fg, bg RGBColor) *RGBStyle {
return s.SetFg(fg).SetBg(bg)
}
// SetFg set fg color
func (s *RGBStyle) SetFg(fg RGBColor) *RGBStyle {
fg[3] = 1
s.fg = fg
return s
}
// SetBg set bg color
func (s *RGBStyle) SetBg(bg RGBColor) *RGBStyle {
bg[3] = 1
s.bg = bg
return s
}
// Print print message
func (s *RGBStyle) Print(a ...interface{}) {
doPrintV2(s.String(), fmt.Sprint(a...))
}
// Printf format and print message
func (s *RGBStyle) Printf(format string, a ...interface{}) {
doPrintV2(s.String(), fmt.Sprintf(format, a...))
}
// Println print message with newline
func (s *RGBStyle) Println(a ...interface{}) {
doPrintlnV2(s.String(), a)
}
// Sprint returns rendered message
func (s *RGBStyle) Sprint(a ...interface{}) string {
return RenderCode(s.String(), a...)
}
// Sprintf returns format and rendered message
func (s *RGBStyle) Sprintf(format string, a ...interface{}) string {
return RenderString(s.Code(), fmt.Sprintf(format, a...))
}
// Code convert to color code string
func (s *RGBStyle) Code() string {
return s.String()
}
// String convert to color code string
func (s *RGBStyle) String() string {
var ss []string
if s.fg[3] == 1 { // last value ensure is enable.
ss = append(ss, fmt.Sprintf(TplFgRGB, s.fg[0], s.fg[1], s.fg[2]))
}
if s.bg[3] == 1 {
ss = append(ss, fmt.Sprintf(TplBgRGB, s.bg[0], s.bg[1], s.bg[2]))
}
return strings.Join(ss, ";")
}
// IsEmpty style
func (s *RGBStyle) IsEmpty() bool {
return s.fg[3] != 1 && s.bg[3] != 1
}

152
vendor/github.com/gookit/color/color_windows.go generated vendored Normal file
View File

@@ -0,0 +1,152 @@
// +build windows
// Display color on windows
// refer:
// golang.org/x/sys/windows
// golang.org/x/crypto/ssh/terminal
// https://docs.microsoft.com/en-us/windows/console
package color
import (
"fmt"
"syscall"
"unsafe"
)
// related docs
// https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences
// https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences#samples
var (
// isMSys bool
kernel32 *syscall.LazyDLL
procGetConsoleMode *syscall.LazyProc
procSetConsoleMode *syscall.LazyProc
)
func init() {
// if at linux, mac, or windows's ConEmu, Cmder, putty
if isSupportColor {
return
}
isLikeInCmd = true
if !Enable {
return
}
// force open
isSupportColor = true
// init simple color code info
// initWinColorsMap()
// load related windows dll
// isMSys = utils.IsMSys()
kernel32 = syscall.NewLazyDLL("kernel32.dll")
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
outHandle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
if err != nil {
fmt.Println(53, err)
return
}
err = EnableVirtualTerminalProcessing(outHandle, true)
saveInternalError(err)
if err != nil {
fmt.Println(err)
// isSupportColor = false
}
// fetch console screen buffer info
// err := getConsoleScreenBufferInfo(uintptr(syscall.Stdout), &defScreenInfo)
}
/*************************************************************
* render full color code on windows(8,16,24bit color)
*************************************************************/
// docs https://docs.microsoft.com/zh-cn/windows/console/getconsolemode#parameters
const (
// equals to docs page's ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
EnableVirtualTerminalProcessingMode uint32 = 0x4
)
// EnableVirtualTerminalProcessing Enable virtual terminal processing
//
// ref from github.com/konsorten/go-windows-terminal-sequences
// doc https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences#samples
//
// Usage:
// err := EnableVirtualTerminalProcessing(syscall.Stdout, true)
// // support print color text
// err = EnableVirtualTerminalProcessing(syscall.Stdout, false)
func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
var mode uint32
// Check if it is currently in the terminal
// err := syscall.GetConsoleMode(syscall.Stdout, &mode)
err := syscall.GetConsoleMode(stream, &mode)
if err != nil {
fmt.Println(92, err)
return err
}
if enable {
mode |= EnableVirtualTerminalProcessingMode
} else {
mode &^= EnableVirtualTerminalProcessingMode
}
ret, _, err := procSetConsoleMode.Call(uintptr(stream), uintptr(mode))
if ret == 0 {
return err
}
return nil
}
// renderColorCodeOnCmd enable cmd color render.
func renderColorCodeOnCmd(fn func()) {
err := EnableVirtualTerminalProcessing(syscall.Stdout, true)
// if is not in terminal, will clear color tag.
if err != nil {
// panic(err)
fn()
return
}
// force open color render
old := ForceOpenColor()
fn()
// revert color setting
isSupportColor = old
err = EnableVirtualTerminalProcessing(syscall.Stdout, false)
if err != nil {
panic(err)
}
}
/*************************************************************
* render simple color code on windows
*************************************************************/
// IsTty returns true if the given file descriptor is a terminal.
func IsTty(fd uintptr) bool {
var st uint32
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
return r != 0 && e == 0
}
// IsTerminal returns true if the given file descriptor is a terminal.
// Usage:
// fd := os.Stdout.Fd()
// fd := uintptr(syscall.Stdout) // for windows
// IsTerminal(fd)
func IsTerminal(fd int) bool {
var st uint32
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
return r != 0 && e == 0
}

5
vendor/github.com/gookit/color/go.mod generated vendored Normal file
View File

@@ -0,0 +1,5 @@
module github.com/gookit/color
go 1.12
require github.com/stretchr/testify v1.3.0

22
vendor/github.com/gookit/color/go.sum generated vendored Normal file
View File

@@ -0,0 +1,22 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
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/go-playground/assert v1.2.1 h1:ad06XqC+TOv0nJWnbULSlh3ehp5uLuQEojZY5Tq8RgI=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gookit/color v1.2.9/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gookit/goutil v0.3.5 h1:95hWrCXcz7wuwlvcHw7YyUbFH0fV15YM0WPioYMcZww=
github.com/gookit/goutil v0.3.5/go.mod h1:OHs5W5Xmfj4pCMXHnMxsDPrCc0SRbHLgJ2qs6wr5fxM=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

307
vendor/github.com/gookit/color/rgb_to_256.go generated vendored Normal file
View File

@@ -0,0 +1,307 @@
package color
import (
"fmt"
"math"
)
// adapted from https://gist.github.com/MicahElliott/719710
var (
lookupTable = map[string]uint8{ // color look-up table
// 8-bit, RGB hex
// Primary 3-bit (8 colors). Unique representation!
"000000": 0,
"800000": 1,
"008000": 2,
"808000": 3,
"000080": 4,
"800080": 5,
"008080": 6,
"c0c0c0": 7,
// Equivalent "bright" versions of original 8 colors.
"808080": 8,
"ff0000": 9,
"00ff00": 10,
"ffff00": 11,
"0000ff": 12,
"ff00ff": 13,
"00ffff": 14,
"ffffff": 15,
// values commented out below are duplicates from the prior sections
// Strictly ascending.
// "000000": 16,
"00005f": 17,
"000087": 18,
"0000af": 19,
"0000d7": 20,
// "0000ff": 21,
"005f00": 22,
"005f5f": 23,
"005f87": 24,
"005faf": 25,
"005fd7": 26,
"005fff": 27,
"008700": 28,
"00875f": 29,
"008787": 30,
"0087af": 31,
"0087d7": 32,
"0087ff": 33,
"00af00": 34,
"00af5f": 35,
"00af87": 36,
"00afaf": 37,
"00afd7": 38,
"00afff": 39,
"00d700": 40,
"00d75f": 41,
"00d787": 42,
"00d7af": 43,
"00d7d7": 44,
"00d7ff": 45,
// "00ff00": 46,
"00ff5f": 47,
"00ff87": 48,
"00ffaf": 49,
"00ffd7": 50,
// "00ffff": 51,
"5f0000": 52,
"5f005f": 53,
"5f0087": 54,
"5f00af": 55,
"5f00d7": 56,
"5f00ff": 57,
"5f5f00": 58,
"5f5f5f": 59,
"5f5f87": 60,
"5f5faf": 61,
"5f5fd7": 62,
"5f5fff": 63,
"5f8700": 64,
"5f875f": 65,
"5f8787": 66,
"5f87af": 67,
"5f87d7": 68,
"5f87ff": 69,
"5faf00": 70,
"5faf5f": 71,
"5faf87": 72,
"5fafaf": 73,
"5fafd7": 74,
"5fafff": 75,
"5fd700": 76,
"5fd75f": 77,
"5fd787": 78,
"5fd7af": 79,
"5fd7d7": 80,
"5fd7ff": 81,
"5fff00": 82,
"5fff5f": 83,
"5fff87": 84,
"5fffaf": 85,
"5fffd7": 86,
"5fffff": 87,
"870000": 88,
"87005f": 89,
"870087": 90,
"8700af": 91,
"8700d7": 92,
"8700ff": 93,
"875f00": 94,
"875f5f": 95,
"875f87": 96,
"875faf": 97,
"875fd7": 98,
"875fff": 99,
"878700": 100,
"87875f": 101,
"878787": 102,
"8787af": 103,
"8787d7": 104,
"8787ff": 105,
"87af00": 106,
"87af5f": 107,
"87af87": 108,
"87afaf": 109,
"87afd7": 110,
"87afff": 111,
"87d700": 112,
"87d75f": 113,
"87d787": 114,
"87d7af": 115,
"87d7d7": 116,
"87d7ff": 117,
"87ff00": 118,
"87ff5f": 119,
"87ff87": 120,
"87ffaf": 121,
"87ffd7": 122,
"87ffff": 123,
"af0000": 124,
"af005f": 125,
"af0087": 126,
"af00af": 127,
"af00d7": 128,
"af00ff": 129,
"af5f00": 130,
"af5f5f": 131,
"af5f87": 132,
"af5faf": 133,
"af5fd7": 134,
"af5fff": 135,
"af8700": 136,
"af875f": 137,
"af8787": 138,
"af87af": 139,
"af87d7": 140,
"af87ff": 141,
"afaf00": 142,
"afaf5f": 143,
"afaf87": 144,
"afafaf": 145,
"afafd7": 146,
"afafff": 147,
"afd700": 148,
"afd75f": 149,
"afd787": 150,
"afd7af": 151,
"afd7d7": 152,
"afd7ff": 153,
"afff00": 154,
"afff5f": 155,
"afff87": 156,
"afffaf": 157,
"afffd7": 158,
"afffff": 159,
"d70000": 160,
"d7005f": 161,
"d70087": 162,
"d700af": 163,
"d700d7": 164,
"d700ff": 165,
"d75f00": 166,
"d75f5f": 167,
"d75f87": 168,
"d75faf": 169,
"d75fd7": 170,
"d75fff": 171,
"d78700": 172,
"d7875f": 173,
"d78787": 174,
"d787af": 175,
"d787d7": 176,
"d787ff": 177,
"d7af00": 178,
"d7af5f": 179,
"d7af87": 180,
"d7afaf": 181,
"d7afd7": 182,
"d7afff": 183,
"d7d700": 184,
"d7d75f": 185,
"d7d787": 186,
"d7d7af": 187,
"d7d7d7": 188,
"d7d7ff": 189,
"d7ff00": 190,
"d7ff5f": 191,
"d7ff87": 192,
"d7ffaf": 193,
"d7ffd7": 194,
"d7ffff": 195,
// "ff0000": 196,
"ff005f": 197,
"ff0087": 198,
"ff00af": 199,
"ff00d7": 200,
// "ff00ff": 201,
"ff5f00": 202,
"ff5f5f": 203,
"ff5f87": 204,
"ff5faf": 205,
"ff5fd7": 206,
"ff5fff": 207,
"ff8700": 208,
"ff875f": 209,
"ff8787": 210,
"ff87af": 211,
"ff87d7": 212,
"ff87ff": 213,
"ffaf00": 214,
"ffaf5f": 215,
"ffaf87": 216,
"ffafaf": 217,
"ffafd7": 218,
"ffafff": 219,
"ffd700": 220,
"ffd75f": 221,
"ffd787": 222,
"ffd7af": 223,
"ffd7d7": 224,
"ffd7ff": 225,
// "ffff00": 226,
"ffff5f": 227,
"ffff87": 228,
"ffffaf": 229,
"ffffd7": 230,
// "ffffff": 231,
// Gray-scale range.
"080808": 232,
"121212": 233,
"1c1c1c": 234,
"262626": 235,
"303030": 236,
"3a3a3a": 237,
"444444": 238,
"4e4e4e": 239,
"585858": 240,
"626262": 241,
"6c6c6c": 242,
"767676": 243,
// "808080": 244,
"8a8a8a": 245,
"949494": 246,
"9e9e9e": 247,
"a8a8a8": 248,
"b2b2b2": 249,
"bcbcbc": 250,
"c6c6c6": 251,
"d0d0d0": 252,
"dadada": 253,
"e4e4e4": 254,
"eeeeee": 255,
}
incs = []uint8{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
)
func rgb2short(r, g, b uint8) uint8 {
res := make([]uint8, 3)
for partI, part := range [3]uint8{r, g, b} {
i := 0
for i < len(incs)-1 {
s, b := incs[i], incs[i+1] // smaller, bigger
if s <= part && part <= b {
s1 := math.Abs(float64(s) - float64(part))
b1 := math.Abs(float64(b) - float64(part))
var closest uint8
if s1 < b1 {
closest = s
} else {
closest = b
}
res[partI] = closest
break
}
i++
}
}
hex := fmt.Sprintf("%02x%02x%02x", res[0], res[1], res[2])
equiv := lookupTable[hex]
return equiv
}

285
vendor/github.com/gookit/color/style.go generated vendored Normal file
View File

@@ -0,0 +1,285 @@
package color
import (
"fmt"
"strings"
)
/*************************************************************
* 16 color Style
*************************************************************/
// Style a 16 color style. can add: fg color, bg color, color options
//
// Example:
// color.Style{color.FgGreen}.Print("message")
type Style []Color
// New create a custom style
//
// Usage:
// color.New(color.FgGreen).Print("message")
// equals to:
// color.Style{color.FgGreen}.Print("message")
func New(colors ...Color) Style {
return colors
}
// Save to styles map
func (s Style) Save(name string) {
AddStyle(name, s)
}
// Render render text
// Usage:
// color.New(color.FgGreen).Render("text")
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text")
func (s Style) Render(a ...interface{}) string {
return RenderCode(s.String(), a...)
}
// Renderln render text line.
// like Println, will add spaces for each argument
// Usage:
// color.New(color.FgGreen).Renderln("text", "more")
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more")
func (s Style) Renderln(a ...interface{}) string {
return RenderWithSpaces(s.String(), a...)
}
// Sprint is alias of the 'Render'
func (s Style) Sprint(a ...interface{}) string {
return RenderCode(s.String(), a...)
}
// Sprintf format and render message.
func (s Style) Sprintf(format string, a ...interface{}) string {
return RenderString(s.String(), fmt.Sprintf(format, a...))
}
// Print render and Print text
func (s Style) Print(a ...interface{}) {
doPrintV2(s.String(), fmt.Sprint(a...))
}
// Printf render and print text
func (s Style) Printf(format string, a ...interface{}) {
doPrintV2(s.Code(), fmt.Sprintf(format, a...))
}
// Println render and print text line
func (s Style) Println(a ...interface{}) {
doPrintlnV2(s.String(), a)
}
// Code convert to code string. returns like "32;45;3"
func (s Style) Code() string {
return s.String()
}
// String convert to code string. returns like "32;45;3"
func (s Style) String() string {
return colors2code(s...)
}
// IsEmpty style
func (s Style) IsEmpty() bool {
return len(s) == 0
}
/*************************************************************
* Theme(extended Style)
*************************************************************/
// Theme definition. extends from Style
type Theme struct {
// Name theme name
Name string
// Style for the theme
Style
}
// NewTheme instance
func NewTheme(name string, style Style) *Theme {
return &Theme{name, style}
}
// Save to themes map
func (t *Theme) Save() {
AddTheme(t.Name, t.Style)
}
// Tips use name as title, only apply style for name
func (t *Theme) Tips(format string, a ...interface{}) {
// only apply style for name
t.Print(strings.ToUpper(t.Name) + ": ")
Printf(format+"\n", a...)
}
// Prompt use name as title, and apply style for message
func (t *Theme) Prompt(format string, a ...interface{}) {
title := strings.ToUpper(t.Name) + ":"
t.Println(title, fmt.Sprintf(format, a...))
}
// Block like Prompt, but will wrap a empty line
func (t *Theme) Block(format string, a ...interface{}) {
title := strings.ToUpper(t.Name) + ":\n"
t.Println(title, fmt.Sprintf(format, a...))
}
/*************************************************************
* Theme: internal themes
*************************************************************/
// internal themes(like bootstrap style)
// Usage:
// color.Info.Print("message")
// color.Info.Printf("a %s message", "test")
// color.Warn.Println("message")
// color.Error.Println("message")
var (
// Info color style
Info = &Theme{"info", Style{OpReset, FgGreen}}
// Note color style
Note = &Theme{"note", Style{OpBold, FgLightCyan}}
// Warn color style
Warn = &Theme{"warning", Style{OpBold, FgYellow}}
// Light color style
Light = &Theme{"light", Style{FgLightWhite, BgBlack}}
// Error color style
Error = &Theme{"error", Style{FgLightWhite, BgRed}}
// Danger color style
Danger = &Theme{"danger", Style{OpBold, FgRed}}
// Debug color style
Debug = &Theme{"debug", Style{OpReset, FgCyan}}
// Notice color style
Notice = &Theme{"notice", Style{OpBold, FgCyan}}
// Comment color style
Comment = &Theme{"comment", Style{OpReset, FgLightYellow}}
// Success color style
Success = &Theme{"success", Style{OpBold, FgGreen}}
// Primary color style
Primary = &Theme{"primary", Style{OpReset, FgBlue}}
// Question color style
Question = &Theme{"question", Style{OpReset, FgMagenta}}
// Secondary color style
Secondary = &Theme{"secondary", Style{FgDarkGray}}
)
// Themes internal defined themes.
// Usage:
// color.Themes["info"].Println("message")
var Themes = map[string]*Theme{
"info": Info,
"note": Note,
"light": Light,
"error": Error,
"debug": Debug,
"danger": Danger,
"notice": Notice,
"success": Success,
"comment": Comment,
"primary": Primary,
"warning": Warn,
"question": Question,
"secondary": Secondary,
}
// AddTheme add a theme and style
func AddTheme(name string, style Style) {
Themes[name] = NewTheme(name, style)
Styles[name] = style
}
// GetTheme get defined theme by name
func GetTheme(name string) *Theme {
return Themes[name]
}
/*************************************************************
* internal styles
*************************************************************/
// Styles internal defined styles, like bootstrap styles.
// Usage:
// color.Styles["info"].Println("message")
var Styles = map[string]Style{
"info": {OpReset, FgGreen},
"note": {OpBold, FgLightCyan},
"light": {FgLightWhite, BgRed},
"error": {FgLightWhite, BgRed},
"danger": {OpBold, FgRed},
"notice": {OpBold, FgCyan},
"success": {OpBold, FgGreen},
"comment": {OpReset, FgMagenta},
"primary": {OpReset, FgBlue},
"warning": {OpBold, FgYellow},
"question": {OpReset, FgMagenta},
"secondary": {FgDarkGray},
}
// some style name alias
var styleAliases = map[string]string{
"err": "error",
"suc": "success",
"warn": "warning",
}
// AddStyle add a style
func AddStyle(name string, s Style) {
Styles[name] = s
}
// GetStyle get defined style by name
func GetStyle(name string) Style {
if s, ok := Styles[name]; ok {
return s
}
if realName, ok := styleAliases[name]; ok {
return Styles[realName]
}
// empty style
return New()
}
/*************************************************************
* quick use style print message
*************************************************************/
// Infof print message with Info style
func Infof(format string, a ...interface{}) {
Info.Printf(format, a...)
}
// Infoln print message with Info style
func Infoln(a ...interface{}) {
Info.Println(a...)
}
// Errorf print message with Error style
func Errorf(format string, a ...interface{}) {
Error.Printf(format, a...)
}
// Errorln print message with Error style
func Errorln(a ...interface{}) {
Error.Println(a...)
}
// Warnf print message with Warn style
func Warnf(format string, a ...interface{}) {
Warn.Printf(format, a...)
}
// Warnln print message with Warn style
func Warnln(a ...interface{}) {
Warn.Println(a...)
}

310
vendor/github.com/gookit/color/tag.go generated vendored Normal file
View File

@@ -0,0 +1,310 @@
package color
import (
"fmt"
"regexp"
"strings"
)
// output colored text like use html tag. (not support windows cmd)
const (
// MatchExpr regex to match color tags
// Notice: golang 不支持反向引用. 即不支持使用 \1 引用第一个匹配 ([a-z=;]+)
// MatchExpr = `<([a-z=;]+)>(.*?)<\/\1>`
// 所以调整一下 统一使用 `</>` 来结束标签,例如 "<info>some text</>"
// 支持自定义颜色属性的tag "<fg=white;bg=blue;op=bold>content</>"
// (?s:...) s - 让 "." 匹配换行
MatchExpr = `<([a-zA-Z_=,;]+)>(?s:(.*?))<\/>`
// AttrExpr regex to match color attributes
AttrExpr = `(fg|bg|op)[\s]*=[\s]*([a-zA-Z,]+);?`
// StripExpr regex used for removing color tags
// StripExpr = `<[\/]?[a-zA-Z=;]+>`
// 随着上面的做一些调整
StripExpr = `<[\/]?[a-zA-Z_=,;]*>`
)
var (
attrRegex = regexp.MustCompile(AttrExpr)
matchRegex = regexp.MustCompile(MatchExpr)
stripRegex = regexp.MustCompile(StripExpr)
)
/*************************************************************
* internal defined color tags
*************************************************************/
// Some internal defined color tags
// Usage: <tag>content text</>
// @notice 加 0 在前面是为了防止之前的影响到现在的设置
var colorTags = map[string]string{
// basic tags,
"red": "0;31",
"blue": "0;34",
"cyan": "0;36",
"black": "0;30",
"green": "0;32",
"white": "1;37",
"default": "0;39", // no color
"normal": "0;39", // no color
"brown": "0;33",
"yellow": "1;33",
"mga": "0;35", // short name
"magenta": "0;35",
"mgb": "1;35", // short name
"magentaB": "1;35", // add bold
// alert tags, like bootstrap's alert
"suc": "1;32", // same "green" and "bold"
"success": "1;32",
"info": "0;32", // same "green",
"comment": "0;33", // same "brown"
"note": "36;1",
"notice": "36;4",
"warn": "0;1;33",
"warning": "0;30;43",
"primary": "0;34",
"danger": "1;31", // same "red" but add bold
"err": "97;41",
"error": "97;41", // fg light white; bg red
// more tags
"lightRed": "1;31",
"light_red": "1;31",
"lightGreen": "1;32",
"light_green": "1;32",
"lightBlue": "1;34",
"light_blue": "1;34",
"lightCyan": "1;36",
"light_cyan": "1;36",
"lightDray": "0;37",
"light_gray": "0;37",
"gray": "0;90",
"darkGray": "0;90",
"dark_gray": "0;90",
"lightYellow": "0;93",
"light_yellow": "0;93",
"lightMagenta": "0;95",
"light_magenta": "0;95",
// extra
"lightRedEx": "0;91",
"light_red_ex": "0;91",
"lightGreenEx": "0;92",
"light_green_ex": "0;92",
"lightBlueEx": "0;94",
"light_blue_ex": "0;94",
"lightCyanEx": "0;96",
"light_cyan_ex": "0;96",
"whiteEx": "0;97;40",
"white_ex": "0;97;40",
// option
"bold": "1",
"underscore": "4",
"reverse": "7",
}
/*************************************************************
* parse color tags
*************************************************************/
// ReplaceTag parse string, replace color tag and return rendered string
func ReplaceTag(str string) string {
// disable handler TAG OR not contains color tag
if !RenderTag || !strings.Contains(str, "</>") {
return str
}
// disabled OR not support color
if !Enable || !isSupportColor {
return ClearTag(str)
}
// find color tags by regex
matched := matchRegex.FindAllStringSubmatch(str, -1)
// item: 0 full text 1 tag name 2 tag content
for _, item := range matched {
full, tag, content := item[0], item[1], item[2]
// custom color in tag: "<fg=white;bg=blue;op=bold>content</>"
if code := ParseCodeFromAttr(tag); len(code) > 0 {
now := RenderString(code, content)
str = strings.Replace(str, full, now, 1)
continue
}
// use defined tag: "<tag>content</>"
if code := GetTagCode(tag); len(code) > 0 {
now := RenderString(code, content)
// old := WrapTag(content, tag) is equals to var 'full'
str = strings.Replace(str, full, now, 1)
}
}
return str
}
// ParseCodeFromAttr parse color attributes.
// attr like:
// "fg=VALUE;bg=VALUE;op=VALUE" // VALUE please see var: FgColors, BgColors, Options
// eg:
// "fg=yellow"
// "bg=red"
// "op=bold,underscore" option is allow multi value
// "fg=white;bg=blue;op=bold"
// "fg=white;op=bold,underscore"
func ParseCodeFromAttr(attr string) (code string) {
if !strings.Contains(attr, "=") {
return
}
attr = strings.Trim(attr, ";=,")
if len(attr) == 0 {
return
}
var colors []Color
matched := attrRegex.FindAllStringSubmatch(attr, -1)
for _, item := range matched {
pos, val := item[1], item[2]
switch pos {
case "fg":
if c, ok := FgColors[val]; ok { // basic fg
colors = append(colors, c)
} else if c, ok := ExFgColors[val]; ok { // extra fg
colors = append(colors, c)
}
case "bg":
if c, ok := BgColors[val]; ok { // basic bg
colors = append(colors, c)
} else if c, ok := ExBgColors[val]; ok { // extra bg
colors = append(colors, c)
}
case "op": // options allow multi value
if strings.Contains(val, ",") {
ns := strings.Split(val, ",")
for _, n := range ns {
if c, ok := Options[n]; ok {
colors = append(colors, c)
}
}
} else if c, ok := Options[val]; ok {
colors = append(colors, c)
}
}
}
return colors2code(colors...)
}
// ClearTag clear all tag for a string
func ClearTag(s string) string {
if !strings.Contains(s, "</>") {
return s
}
return stripRegex.ReplaceAllString(s, "")
}
/*************************************************************
* helper methods
*************************************************************/
// GetTagCode get color code by tag name
func GetTagCode(name string) string {
if code, ok := colorTags[name]; ok {
return code
}
return ""
}
// ApplyTag for messages
func ApplyTag(tag string, a ...interface{}) string {
return RenderCode(GetTagCode(tag), a...)
}
// WrapTag wrap a tag for a string "<tag>content</>"
func WrapTag(s string, tag string) string {
if s == "" || tag == "" {
return s
}
return fmt.Sprintf("<%s>%s</>", tag, s)
}
// GetColorTags get all internal color tags
func GetColorTags() map[string]string {
return colorTags
}
// IsDefinedTag is defined tag name
func IsDefinedTag(name string) bool {
_, ok := colorTags[name]
return ok
}
/*************************************************************
* Tag extra
*************************************************************/
// Tag value is a defined style name
// Usage:
// Tag("info").Println("message")
type Tag string
// Print messages
func (tg Tag) Print(a ...interface{}) {
name := string(tg)
str := fmt.Sprint(a...)
if stl := GetStyle(name); !stl.IsEmpty() {
stl.Print(str)
} else {
doPrintV2(GetTagCode(name), str)
}
}
// Printf format and print messages
func (tg Tag) Printf(format string, a ...interface{}) {
name := string(tg)
str := fmt.Sprintf(format, a...)
if stl := GetStyle(name); !stl.IsEmpty() {
stl.Print(str)
} else {
doPrintV2(GetTagCode(name), str)
}
}
// Println messages line
func (tg Tag) Println(a ...interface{}) {
name := string(tg)
if stl := GetStyle(name); !stl.IsEmpty() {
stl.Println(a...)
} else {
doPrintlnV2(GetTagCode(name), a)
}
}
// Sprint render messages
func (tg Tag) Sprint(a ...interface{}) string {
name := string(tg)
// if stl := GetStyle(name); !stl.IsEmpty() {
// return stl.Render(args...)
// }
return RenderCode(GetTagCode(name), a...)
}
// Sprintf format and render messages
func (tg Tag) Sprintf(format string, a ...interface{}) string {
tag := string(tg)
str := fmt.Sprintf(format, a...)
return RenderString(GetTagCode(tag), str)
}

351
vendor/github.com/gookit/color/utils.go generated vendored Normal file
View File

@@ -0,0 +1,351 @@
package color
import (
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"syscall"
)
// Support color:
// "TERM=xterm"
// "TERM=xterm-vt220"
// "TERM=xterm-256color"
// "TERM=screen-256color"
// "TERM=tmux-256color"
// "TERM=rxvt-unicode-256color"
// Don't support color:
// "TERM=cygwin"
var specialColorTerms = map[string]bool{
"alacritty": true,
"screen-256color": true,
"tmux-256color": true,
"rxvt-unicode-256color": true,
}
// IsConsole Determine whether w is one of stderr, stdout, stdin
func IsConsole(w io.Writer) bool {
o, ok := w.(*os.File)
if !ok {
return false
}
fd := o.Fd()
// fix: cannot use 'o == os.Stdout' to compare
return fd == uintptr(syscall.Stdout) || fd == uintptr(syscall.Stdin) || fd == uintptr(syscall.Stderr)
}
// IsMSys msys(MINGW64) environment, does not necessarily support color
func IsMSys() bool {
// like "MSYSTEM=MINGW64"
if len(os.Getenv("MSYSTEM")) > 0 {
return true
}
return false
}
// IsSupportColor check current console is support color.
//
// Supported:
// linux, mac, or windows's ConEmu, Cmder, putty, git-bash.exe
// Not support:
// windows cmd.exe, powerShell.exe
func IsSupportColor() bool {
envTerm := os.Getenv("TERM")
if strings.Contains(envTerm, "xterm") {
return true
}
// it's special color term
if _, ok := specialColorTerms[envTerm]; ok {
return true
}
// like on ConEmu software, e.g "ConEmuANSI=ON"
if os.Getenv("ConEmuANSI") == "ON" {
return true
}
// like on ConEmu software, e.g "ANSICON=189x2000 (189x43)"
if os.Getenv("ANSICON") != "" {
return true
}
// up: if support 256-color, can also support basic color.
return IsSupport256Color()
}
// IsSupport256Color render
func IsSupport256Color() bool {
// "TERM=xterm-256color"
// "TERM=screen-256color"
// "TERM=tmux-256color"
// "TERM=rxvt-unicode-256color"
supported := strings.Contains(os.Getenv("TERM"), "256color")
if !supported {
// up: if support true-color, can also support 256-color.
supported = IsSupportTrueColor()
}
return supported
}
// IsSupportTrueColor render. IsSupportRGBColor
func IsSupportTrueColor() bool {
// "COLORTERM=truecolor"
return strings.Contains(os.Getenv("COLORTERM"), "truecolor")
}
// Hex2rgb alias of the HexToRgb()
func Hex2rgb(hex string) []int { return HexToRgb(hex) }
// HexToRGB alias of the HexToRgb()
func HexToRGB(hex string) []int { return HexToRgb(hex) }
// HexToRgb convert hex color string to RGB numbers
// Usage:
// rgb := HexToRgb("ccc") // rgb: [204 204 204]
// rgb := HexToRgb("aabbcc") // rgb: [170 187 204]
// rgb := HexToRgb("#aabbcc") // rgb: [170 187 204]
// rgb := HexToRgb("0xad99c0") // rgb: [170 187 204]
func HexToRgb(hex string) (rgb []int) {
hex = strings.TrimSpace(hex)
if hex == "" {
return
}
// like from css. eg "#ccc" "#ad99c0"
if hex[0] == '#' {
hex = hex[1:]
}
hex = strings.ToLower(hex)
switch len(hex) {
case 3: // "ccc"
hex = string([]byte{hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]})
case 8: // "0xad99c0"
hex = strings.TrimPrefix(hex, "0x")
}
// recheck
if len(hex) != 6 {
return
}
// convert string to int64
if i64, err := strconv.ParseInt(hex, 16, 32); err == nil {
color := int(i64)
// parse int
rgb = make([]int, 3)
rgb[0] = color >> 16
rgb[1] = (color & 0x00FF00) >> 8
rgb[2] = color & 0x0000FF
}
return
}
// Rgb2hex alias of the RgbToHex()
func Rgb2hex(rgb []int) string { return RgbToHex(rgb) }
// RgbToHex convert RGB to hex code
// Usage:
// hex := RgbToHex([]int{170, 187, 204}) // hex: "aabbcc"
func RgbToHex(rgb []int) string {
hexNodes := make([]string, len(rgb))
for _, v := range rgb {
hexNodes = append(hexNodes, strconv.FormatInt(int64(v), 16))
}
return strings.Join(hexNodes, "")
}
/*************************************************************
* print methods(will auto parse color tags)
*************************************************************/
// Print render color tag and print messages
func Print(a ...interface{}) {
Fprint(output, a...)
}
// Printf format and print messages
func Printf(format string, a ...interface{}) {
Fprintf(output, format, a...)
}
// Println messages with new line
func Println(a ...interface{}) {
Fprintln(output, a...)
}
// Fprint print rendered messages to writer
// Notice: will ignore print error
func Fprint(w io.Writer, a ...interface{}) {
_, err := fmt.Fprint(w, Render(a...))
saveInternalError(err)
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// _, _ = fmt.Fprint(w, Render(a...))
// })
// } else {
// _, _ = fmt.Fprint(w, Render(a...))
// }
}
// Fprintf print format and rendered messages to writer.
// Notice: will ignore print error
func Fprintf(w io.Writer, format string, a ...interface{}) {
str := fmt.Sprintf(format, a...)
_, err := fmt.Fprint(w, ReplaceTag(str))
saveInternalError(err)
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// _, _ = fmt.Fprint(w, ReplaceTag(str))
// })
// } else {
// _, _ = fmt.Fprint(w, ReplaceTag(str))
// }
}
// Fprintln print rendered messages line to writer
// Notice: will ignore print error
func Fprintln(w io.Writer, a ...interface{}) {
str := formatArgsForPrintln(a)
_, err := fmt.Fprintln(w, ReplaceTag(str))
saveInternalError(err)
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// _, _ = fmt.Fprintln(w, ReplaceTag(str))
// })
// } else {
// _, _ = fmt.Fprintln(w, ReplaceTag(str))
// }
}
// Lprint passes colored messages to a log.Logger for printing.
// Notice: should be goroutine safe
func Lprint(l *log.Logger, a ...interface{}) {
l.Print(Render(a...))
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// l.Print(Render(a...))
// })
// } else {
// l.Print(Render(a...))
// }
}
// Render parse color tags, return rendered string.
// Usage:
// text := Render("<info>hello</> <cyan>world</>!")
// fmt.Println(text)
func Render(a ...interface{}) string {
if len(a) == 0 {
return ""
}
return ReplaceTag(fmt.Sprint(a...))
}
// Sprint parse color tags, return rendered string
func Sprint(args ...interface{}) string {
return Render(args...)
}
// Sprintf format and return rendered string
func Sprintf(format string, a ...interface{}) string {
return ReplaceTag(fmt.Sprintf(format, a...))
}
// String alias of the ReplaceTag
func String(s string) string {
return ReplaceTag(s)
}
// Text alias of the ReplaceTag
func Text(s string) string {
return ReplaceTag(s)
}
/*************************************************************
* helper methods for print
*************************************************************/
// its Win system. linux windows darwin
// func isWindows() bool {
// return runtime.GOOS == "windows"
// }
func saveInternalError(err error) {
if err != nil {
errors = append(errors, err)
}
}
// new implementation, support render full color code on pwsh.exe, cmd.exe
func doPrintV2(code, str string) {
_, err := fmt.Fprint(output, RenderString(code, str))
saveInternalError(err)
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// _, _ = fmt.Fprint(output, RenderString(code, str))
// })
// } else {
// _, _ = fmt.Fprint(output, RenderString(code, str))
// }
}
// new implementation, support render full color code on pwsh.exe, cmd.exe
func doPrintlnV2(code string, args []interface{}) {
str := formatArgsForPrintln(args)
_, err := fmt.Fprintln(output, RenderString(code, str))
saveInternalError(err)
// if isLikeInCmd {
// renderColorCodeOnCmd(func() {
// _, _ = fmt.Fprintln(output, RenderString(code, str))
// })
// } else {
// _, _ = fmt.Fprintln(output, RenderString(code, str))
// }
}
func stringToArr(str, sep string) (arr []string) {
str = strings.TrimSpace(str)
if str == "" {
return
}
ss := strings.Split(str, sep)
for _, val := range ss {
if val = strings.TrimSpace(val); val != "" {
arr = append(arr, val)
}
}
return
}
// if use Println, will add spaces for each arg
func formatArgsForPrintln(args []interface{}) (message string) {
if ln := len(args); ln == 0 {
message = ""
} else if ln == 1 {
message = fmt.Sprint(args[0])
} else {
message = fmt.Sprintln(args...)
// clear last "\n"
message = message[:len(message)-1]
}
return
}

28
vendor/github.com/gosuri/uilive/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,28 @@
language: go
sudo: false
matrix:
include:
- go: 1.11.x
os: linux
- go: 1.12.x
os: linux
- go: 1.11.x
os: linux
env: CROSS_COMPILE=true
- go: 1.12.x
os: linux
env: CROSS_COMPILE=true
- go: 1.11.x
os: osx
- go: 1.12.x
os: osx
install:
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then go get github.com/mattn/go-isatty ; fi
- go get -t -v ./...
script:
- go build
- go test
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then env GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -v; fi

10
vendor/github.com/gosuri/uilive/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,10 @@
MIT License
===========
Copyright (c) 2015, Greg Osuri
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.

7
vendor/github.com/gosuri/uilive/Makefile generated vendored Normal file
View File

@@ -0,0 +1,7 @@
test:
@go test -race .
examples:
@go run -race ./example
.PHONY: test examples

31
vendor/github.com/gosuri/uilive/README.md generated vendored Normal file
View File

@@ -0,0 +1,31 @@
# uilive [![GoDoc](https://godoc.org/github.com/gosuri/uilive?status.svg)](https://godoc.org/github.com/gosuri/uilive) [![Build Status](https://travis-ci.org/gosuri/uilive.svg?branch=master)](https://travis-ci.org/gosuri/uilive)
uilive is a go library for updating terminal output in realtime. It provides a buffered [io.Writer](https://golang.org/pkg/io/#Writer) that is flushed at a timed interval. uilive powers [uiprogress](https://github.com/gosuri/uiprogress).
## Usage Example
Calling `uilive.New()` will create a new writer. To start rendering, simply call `writer.Start()` and update the ui by writing to the `writer`. Full source for the below example is in [example/main.go](example/main.go).
```go
writer := uilive.New()
// start listening for updates and render
writer.Start()
for i := 0; i <= 100; i++ {
fmt.Fprintf(writer, "Downloading.. (%d/%d) GB\n", i, 100)
time.Sleep(time.Millisecond * 5)
}
fmt.Fprintln(writer, "Finished: Downloaded 100GB")
writer.Stop() // flush and stop rendering
```
The above will render
![example](doc/example.gif)
## Installation
```sh
$ go get -v github.com/gosuri/uilive
```

2
vendor/github.com/gosuri/uilive/doc.go generated vendored Normal file
View File

@@ -0,0 +1,2 @@
// Package uilive provides a writer that live updates the terminal. It provides a buffered io.Writer that is flushed at a timed interval.
package uilive

3
vendor/github.com/gosuri/uilive/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/gosuri/uilive
go 1.10

37
vendor/github.com/gosuri/uilive/terminal_size.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
// +build !windows
package uilive
import (
"os"
"runtime"
"syscall"
"unsafe"
)
type windowSize struct {
rows uint16
cols uint16
}
var out *os.File
var err error
var sz windowSize
func getTermSize() (int, int) {
if runtime.GOOS == "openbsd" {
out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
return 0, 0
}
} else {
out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0)
if err != nil {
return 0, 0
}
}
_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
return int(sz.cols), int(sz.rows)
}

View File

@@ -0,0 +1,24 @@
// +build windows
package uilive
import (
"os"
"unsafe"
)
func getTermSize() (int, int) {
out, err := os.Open("CONOUT$")
if err != nil {
return 0, 0
}
defer out.Close()
var csbi consoleScreenBufferInfo
ret, _, _ := procGetConsoleScreenBufferInfo.Call(out.Fd(), uintptr(unsafe.Pointer(&csbi)))
if ret == 0 {
return 0, 0
}
return int(csbi.window.right - csbi.window.left + 1), int(csbi.window.bottom - csbi.window.top + 1)
}

173
vendor/github.com/gosuri/uilive/writer.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package uilive
import (
"bytes"
"errors"
"io"
"os"
"sync"
"time"
)
// ESC is the ASCII code for escape character
const ESC = 27
// RefreshInterval is the default refresh interval to update the ui
var RefreshInterval = time.Millisecond
var overFlowHandled bool
var termWidth int
// Out is the default output writer for the Writer
var Out = io.Writer(os.Stdout)
// ErrClosedPipe is the error returned when trying to writer is not listening
var ErrClosedPipe = errors.New("uilive: read/write on closed pipe")
// FdWriter is a writer with a file descriptor.
type FdWriter interface {
io.Writer
Fd() uintptr
}
// Writer is a buffered the writer that updates the terminal. The contents of writer will be flushed on a timed interval or when Flush is called.
type Writer struct {
// Out is the writer to write to
Out io.Writer
// RefreshInterval is the time the UI sould refresh
RefreshInterval time.Duration
ticker *time.Ticker
tdone chan bool
buf bytes.Buffer
mtx *sync.Mutex
lineCount int
}
type bypass struct {
writer *Writer
}
type newline struct {
writer *Writer
}
// New returns a new Writer with defaults
func New() *Writer {
termWidth, _ = getTermSize()
if termWidth != 0 {
overFlowHandled = true
}
return &Writer{
Out: Out,
RefreshInterval: RefreshInterval,
mtx: &sync.Mutex{},
}
}
// Flush writes to the out and resets the buffer. It should be called after the last call to Write to ensure that any data buffered in the Writer is written to output.
// Any incomplete escape sequence at the end is considered complete for formatting purposes.
// An error is returned if the contents of the buffer cannot be written to the underlying output stream
func (w *Writer) Flush() error {
w.mtx.Lock()
defer w.mtx.Unlock()
// do nothing if buffer is empty
if len(w.buf.Bytes()) == 0 {
return nil
}
w.clearLines()
lines := 0
var currentLine bytes.Buffer
for _, b := range w.buf.Bytes() {
if b == '\n' {
lines++
currentLine.Reset()
} else {
currentLine.Write([]byte{b})
if overFlowHandled && currentLine.Len() > termWidth {
lines++
currentLine.Reset()
}
}
}
w.lineCount = lines
_, err := w.Out.Write(w.buf.Bytes())
w.buf.Reset()
return err
}
// Start starts the listener in a non-blocking manner
func (w *Writer) Start() {
if w.ticker == nil {
w.ticker = time.NewTicker(w.RefreshInterval)
w.tdone = make(chan bool)
}
go w.Listen()
}
// Stop stops the listener that updates the terminal
func (w *Writer) Stop() {
w.Flush()
w.tdone <- true
<-w.tdone
}
// Listen listens for updates to the writer's buffer and flushes to the out provided. It blocks the runtime.
func (w *Writer) Listen() {
for {
select {
case <-w.ticker.C:
if w.ticker != nil {
_ = w.Flush()
}
case <-w.tdone:
w.mtx.Lock()
w.ticker.Stop()
w.ticker = nil
w.mtx.Unlock()
close(w.tdone)
return
}
}
}
// Write save the contents of buf to the writer b. The only errors returned are ones encountered while writing to the underlying buffer.
func (w *Writer) Write(buf []byte) (n int, err error) {
w.mtx.Lock()
defer w.mtx.Unlock()
return w.buf.Write(buf)
}
// Bypass creates an io.Writer which allows non-buffered output to be written to the underlying output
func (w *Writer) Bypass() io.Writer {
return &bypass{writer: w}
}
func (b *bypass) Write(p []byte) (int, error) {
b.writer.mtx.Lock()
defer b.writer.mtx.Unlock()
b.writer.clearLines()
b.writer.lineCount = 0
return b.writer.Out.Write(p)
}
// Newline creates an io.Writer which allows buffered output to be written to the underlying output. This enable writing
// to multiple lines at once.
func (w *Writer) Newline() io.Writer {
return &newline{writer: w}
}
func (n *newline) Write(p []byte) (int, error) {
n.writer.mtx.Lock()
defer n.writer.mtx.Unlock()
return n.writer.buf.Write(p)
}

15
vendor/github.com/gosuri/uilive/writer_posix.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
// +build !windows
package uilive
import (
"fmt"
"strings"
)
// clear the line and move the cursor up
var clear = fmt.Sprintf("%c[%dA%c[2K", ESC, 1, ESC)
func (w *Writer) clearLines() {
_, _ = fmt.Fprint(w.Out, strings.Repeat(clear, w.lineCount))
}

74
vendor/github.com/gosuri/uilive/writer_windows.go generated vendored Normal file
View File

@@ -0,0 +1,74 @@
// +build windows
package uilive
import (
"fmt"
"strings"
"syscall"
"unsafe"
"github.com/mattn/go-isatty"
)
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
var (
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
)
// clear the line and move the cursor up
var clear = fmt.Sprintf("%c[%dA%c[2K\r", ESC, 0, ESC)
type short int16
type dword uint32
type word uint16
type coord struct {
x short
y short
}
type smallRect struct {
left short
top short
right short
bottom short
}
type consoleScreenBufferInfo struct {
size coord
cursorPosition coord
attributes word
window smallRect
maximumWindowSize coord
}
func (w *Writer) clearLines() {
f, ok := w.Out.(FdWriter)
if ok && !isatty.IsTerminal(f.Fd()) {
ok = false
}
if !ok {
_, _ = fmt.Fprint(w.Out, strings.Repeat(clear, w.lineCount))
return
}
fd := f.Fd()
var csbi consoleScreenBufferInfo
_, _, _ = procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi)))
for i := 0; i < w.lineCount; i++ {
// move the cursor up
csbi.cursorPosition.y--
_, _, _ = procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition))))
// clear the line
cursor := coord{
x: csbi.window.left,
y: csbi.window.top + csbi.cursorPosition.y,
}
var count, w dword
count = dword(csbi.size.x)
_, _, _ = procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
}
}

8
vendor/github.com/mattn/go-runewidth/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,8 @@
language: go
go:
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL

21
vendor/github.com/mattn/go-runewidth/LICENSE generated vendored Normal file
View 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.mkd generated vendored Normal file
View File

@@ -0,0 +1,27 @@
go-runewidth
============
[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth)
[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD)
[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth)
[![Go Report Card](https://goreportcard.com/badge/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

3
vendor/github.com/mattn/go-runewidth/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/mattn/go-runewidth
go 1.9

258
vendor/github.com/mattn/go-runewidth/runewidth.go generated vendored Normal file
View File

@@ -0,0 +1,258 @@
package runewidth
import (
"os"
)
//go:generate go run script/generate.go
var (
// EastAsianWidth will be set true if the current locale is CJK
EastAsianWidth bool
// ZeroWidthJoiner is flag to set to use UTR#51 ZWJ
ZeroWidthJoiner bool
// DefaultCondition is a condition in current locale
DefaultCondition = &Condition{}
)
func init() {
handleEnv()
}
func handleEnv() {
env := os.Getenv("RUNEWIDTH_EASTASIAN")
if env == "" {
EastAsianWidth = IsEastAsian()
} else {
EastAsianWidth = env == "1"
}
// update DefaultCondition
DefaultCondition.EastAsianWidth = EastAsianWidth
DefaultCondition.ZeroWidthJoiner = ZeroWidthJoiner
}
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 {
// func (t table) IncludesRune(r rune) 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
ZeroWidthJoiner bool
}
// NewCondition return new instance of Condition which is current locale.
func NewCondition() *Condition {
return &Condition{
EastAsianWidth: EastAsianWidth,
ZeroWidthJoiner: ZeroWidthJoiner,
}
}
// RuneWidth returns the number of cells in r.
// See http://www.unicode.org/reports/tr11/
func (c *Condition) RuneWidth(r rune) int {
switch {
case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining, notassigned):
return 0
case (c.EastAsianWidth && IsAmbiguousWidth(r)) || inTables(r, doublewidth):
return 2
default:
return 1
}
}
func (c *Condition) stringWidth(s string) (width int) {
for _, r := range []rune(s) {
width += c.RuneWidth(r)
}
return width
}
func (c *Condition) stringWidthZeroJoiner(s string) (width int) {
r1, r2 := rune(0), rune(0)
for _, r := range []rune(s) {
if r == 0xFE0E || r == 0xFE0F {
continue
}
w := c.RuneWidth(r)
if r2 == 0x200D && inTables(r, emoji) && inTables(r1, emoji) {
if width < w {
width = w
}
} else {
width += w
}
r1, r2 = r2, r
}
return width
}
// StringWidth return width as you can see
func (c *Condition) StringWidth(s string) (width int) {
if c.ZeroWidthJoiner {
return c.stringWidthZeroJoiner(s)
}
return c.stringWidth(s)
}
// 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
}
r := []rune(s)
tw := c.StringWidth(tail)
w -= tw
width := 0
i := 0
for ; i < len(r); i++ {
cw := c.RuneWidth(r[i])
if width+cw > w {
break
}
width += cw
}
return string(r[0:i]) + 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 := 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)
}

View 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
View 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
}

View File

@@ -0,0 +1,79 @@
// +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_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)
}

427
vendor/github.com/mattn/go-runewidth/runewidth_table.go generated vendored Normal file
View File

@@ -0,0 +1,427 @@
package runewidth
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0D00, 0x0D01},
{0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ABE},
{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},
{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, 0x31BA},
{0x31C0, 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, 0x16FE3}, {0x17000, 0x187F7}, {0x18800, 0x18AF2},
{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, 0x1F6D5}, {0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FA}, {0x1F7E0, 0x1F7EB}, {0x1F90D, 0x1F971},
{0x1F973, 0x1F976}, {0x1F97A, 0x1F9A2}, {0x1F9A5, 0x1F9AA},
{0x1F9AE, 0x1F9CA}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA73},
{0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA82}, {0x1FA90, 0x1FA95},
{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 notassigned = table{
{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, 0x08BD},
{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},
{0x0B56, 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, 0x0D03},
{0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D44},
{0x0D46, 0x0D48}, {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63},
{0x0D66, 0x0D7F}, {0x0D82, 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, 0x1ABE}, {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}, {0x2B98, 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, 0x2E4F}, {0x303F, 0x303F},
{0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
{0xA700, 0xA7BF}, {0xA7C2, 0xA7C6}, {0xA7F7, 0xA82B},
{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, 0xAB67}, {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, 0x1019B}, {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}, {0x10F00, 0x10F27}, {0x10F30, 0x10F59},
{0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x1106F},
{0x1107F, 0x110C1}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11146},
{0x11150, 0x11176}, {0x11180, 0x111CD}, {0x111D0, 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, 0x11459}, {0x1145B, 0x1145B},
{0x1145D, 0x1145F}, {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, 0x118FF}, {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}, {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, 0x1F10C}, {0x1F12E, 0x1F12F},
{0x1F16A, 0x1F16C}, {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}, {0x1F900, 0x1F90B},
{0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D}, {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, 0x1FFFD},
}

View 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
}

21
vendor/github.com/mitchellh/go-glint/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Mitchell Hashimoto
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.

79
vendor/github.com/mitchellh/go-glint/README.md generated vendored Normal file
View File

@@ -0,0 +1,79 @@
# go-glint [![Godoc](https://godoc.org/github.com/mitchellh/go-glint?status.svg)](https://godoc.org/github.com/mitchellh/go-glint)
Glint is a component-based UI framework specifically targeted towards
command-line interfaces. This allows you to create highly dynamic CLI interfaces
using shared, easily testable components. Glint uses a Flexbox implementation
to make it easy to lay out components in the CLI, including paddings, margins,
and more.
**API Status: Unstable.** We're still actively working on the API and
may change it in backwards incompatible ways. See the roadmap section in
particular for work that may impact the API. In particular, we have
integrated this library into [Waypoint](https://github.com/hashicorp/waypoint),
and the experience of using this library in the real world will likely drive major
changes.
## Example
The example below shows a simple dynamic counter:
```go
func main() {
var counter uint32
go func() {
for {
time.Sleep(100 * time.Millisecond)
atomic.AddUint32(&counter, 1)
}
}()
d := glint.New()
d.Append(
glint.Style(
glint.TextFunc(func(rows, cols uint) string {
return fmt.Sprintf("%d tests passed", atomic.LoadUint32(&counter))
}),
glint.Color("green"),
),
)
d.Render(context.Background())
}
```
Output:
![Example](https://user-images.githubusercontent.com/1299/92431533-9baf8000-f14c-11ea-94ad-8ff97ed26fec.gif)
## Roadmap
Glint is still an early stage project and there is a lot that we want to
improve on. This may introduce some backwards incompatibilities but we are
trying to stabilize the API as quickly as possible.
* **Non-interactive interfaces.** We want to add support for rendering to
non-interactive interfaces and allowing components to provide custom behavior
in these cases. For now, users of Glint should detect non-interactivity and
avoid using Glint.
* **Windows PowerShell and Cmd.** Glint works fine in ANSI-compatible terminals
on Windows, but doesn't work with PowerShell and Cmd. We want to make this
work.
* **Dirty tracking.** Glint currently rerenders the entire frame on each
tick. I'd like components to be able to report if there are changes (if they
are "dirty") and need to be rerendered. We could then more efficiently
recalculate layouts and rerender outputs.
* **User Input.** Glint should be able to query for user input and render
this within its existing set of components.
* **Expose styling to custom renderers.** Currently the `Style` component
is a special-case for the terminal renderer to render colors. I'd like to expose
the styles in a way that other renderers could use it in some meaningful way.
## Thanks
This library is heavily inspired by the [Ink project](https://github.com/vadimdemedes/ink).
I saw this project and thought that having a central render loop along with
a full layout engine was a fantastic idea. Most of my projects are in Go
so I wanted to be able to realize these benefits with Go. Thank you!

89
vendor/github.com/mitchellh/go-glint/component.go generated vendored Normal file
View File

@@ -0,0 +1,89 @@
package glint
import (
"context"
"github.com/mitchellh/go-glint/internal/layout"
)
// Components are the individual items that are rendered within a document.
type Component interface {
// Body returns the body of this component. This can be another custom
// component or a standard component such as Text.
//
// The context parameter is used to send parameters across multiple
// components. It should not be used for timeouts; Body should aim to
// not block ever since this can block the render loop.
//
// Components are highly encouraged to support finalization (see
// ComponentFinalizer). Components can finalize early by wrapping
// their body in a Finalize built-in component. Finalization allows
// the renderer to highly optimize output.
Body(context.Context) Component
}
// ComponentFinalizer allows components to be notified they are going to
// be finalized. A finalized component may never be re-rendered again. The
// next call to Body should be considered the final call.
//
// In a Document, if the component list has a set of finalized components
// at the front, the renderer will draw it once and only re-draw non-finalized
// components. For example, consider a document that is a set of text components
// followed by a progress bar. If the text components are static, then they
// will be written to the output once and only the progress bar will redraw.
//
// Currently, Body may be called multiple times after Finalize. Implementers
// should return the same result after being finalized.
type ComponentFinalizer interface {
Component
// Finalize notifies the component that it will be finalized. This may
// be called multiple times.
Finalize()
}
// ComponentMounter allows components to be notified when they are
// mounted and unmounted. A mounted component is one that is added to
// a render tree for the first time. A component is unmounted when it is
// removed from the render tree.
//
// The callbacks here may be called multiple times under certain scenarios:
// (1) a component is used in multiple Document instances, (2) a component
// is unmounted and then remounted in the future.
//
// A component mounted multiple times in the same render tree does NOT
// have the mount callbacks called multiple times.
//
// A good use case for this interface is setting up and cleaning up resources.
type ComponentMounter interface {
Component
// Mount is called when the component is added to a render tree. The
// context given to this is used to access data set by Glint and the
// renderer in use.
Mount(context.Context)
// Unmount is called when the component is removed from a render tree.
// This will be called under ANY scenario where the component is
// removed from the render tree, including finalization.
Unmount(context.Context)
}
// componentLayout can be implemented to set custom layout settings
// for the component. This can only be implemented by internal components
// since we use an internal library.
//
// End users should use the "Layout" component to set layout options.
type componentLayout interface {
Component
// Layout should return the layout settings for this component.
Layout() *layout.Builder
}
// terminalComponent is an embeddable struct for internal usage that
// satisfies Component. This is used since terminal components are handled
// as special cases.
type terminalComponent struct{}
func (terminalComponent) Body(context.Context) Component { return nil }

View File

@@ -0,0 +1,38 @@
package components
import (
"context"
"github.com/cheggaaa/pb/v3"
"github.com/mitchellh/go-glint"
)
// ProgressElement renders a progress bar. This wraps the cheggaaa/pb package
// since that provides important functionality. This uses single call renders
// to render the progress bar as values change.
type ProgressElement struct {
*pb.ProgressBar
}
// Progress creates a new progress bar element with the given total.
// For more fine-grained control, please construct a ProgressElement
// directly.
func Progress(total int) *ProgressElement {
return &ProgressElement{
ProgressBar: pb.New(total),
}
}
func (el *ProgressElement) Body(context.Context) glint.Component {
// If we have no progress bar render nothing.
if el.ProgressBar == nil {
return nil
}
// Write the current progress
return glint.TextFunc(func(rows, cols uint) string {
el.ProgressBar.SetWidth(int(cols))
return el.ProgressBar.String()
})
}

View File

@@ -0,0 +1,112 @@
package components
import (
"container/ring"
"context"
"math"
"sync"
"github.com/mitchellh/go-glint"
)
// SparklineComponent renders a sparkline graph.
type SparklineComponent struct {
sync.Mutex
// If set, this will style the peak value.
PeakStyle []glint.StyleOption
values *ring.Ring
}
// Sparkline creates a SparklineComponent with the given set of initial values.
// These initial values will also specify the max width for this sparkline
// unless values are replaced with Set.
func Sparkline(values []uint) *SparklineComponent {
var c SparklineComponent
c.Set(values)
return &c
}
// Set sets the full set of values to the given slice. This will also reset
// the size of the sparkline to this length.
func (c *SparklineComponent) Set(values []uint) {
c.Lock()
defer c.Unlock()
c.values = ring.New(len(values))
for _, v := range values {
c.values.Value = v
c.values = c.values.Next()
}
}
// Append adds the given values to the end of the values buffer. The buffer
// size is determined by the values list given in Sparkline or Set. This will
// overwrite the oldest values.
func (c *SparklineComponent) Append(values ...uint) {
c.Lock()
defer c.Unlock()
for _, v := range values {
c.values.Value = v
c.values = c.values.Next()
}
}
func (c *SparklineComponent) valuesSlice() []uint {
result := make([]uint, c.values.Len())
for i := range result {
result[i] = c.values.Value.(uint)
c.values = c.values.Next()
}
return result
}
func (c *SparklineComponent) Body(context.Context) glint.Component {
c.Lock()
defer c.Unlock()
values := c.valuesSlice()
// If we have nothing we render nothing
if len(values) == 0 {
return nil
}
// Find the max
max := values[0]
if len(values) > 1 {
for _, v := range values[1:] {
if v > max {
max = v
}
}
}
// Build each symbol
peak := false
parts := make([]glint.Component, len(values))
for i, v := range values {
symbolIdx := int(math.Ceil(float64(v) / float64(max) * float64(len(sparklineSymbols)-1)))
parts[i] = glint.Text(string(sparklineSymbols[symbolIdx]))
if len(c.PeakStyle) > 0 && v == max && !peak {
peak = true
parts[i] = glint.Style(parts[i], c.PeakStyle...)
}
}
// Render them in a row
return glint.Layout(parts...).Row()
}
var sparklineSymbols = []rune{
'\u2581',
'\u2582',
'\u2583',
'\u2584',
'\u2585',
'\u2586',
'\u2587',
'\u2588',
}

View File

@@ -0,0 +1,36 @@
package components
import (
"context"
"time"
"github.com/mitchellh/go-glint"
"github.com/tj/go-spin"
)
// Spinner creates a new spinner. The created spinner should NOT be started
// or data races will occur that can result in a panic.
func Spinner() *SpinnerComponent {
// Create our spinner and setup our default frames
s := spin.New()
s.Set(spin.Default)
return &SpinnerComponent{
s: s,
}
}
type SpinnerComponent struct {
s *spin.Spinner
last time.Time
}
func (c *SpinnerComponent) Body(context.Context) glint.Component {
current := time.Now()
if c.last.IsZero() || current.Sub(c.last) > 150*time.Millisecond {
c.last = current
c.s.Next()
}
return glint.Text(c.s.Current())
}

View File

@@ -0,0 +1,23 @@
package components
import (
"context"
"time"
"github.com/mitchellh/go-glint"
)
// Stopwatch creates a new stopwatch component that starts at the given time.
func Stopwatch(start time.Time) *StopwatchComponent {
return &StopwatchComponent{
start: start,
}
}
type StopwatchComponent struct {
start time.Time
}
func (c *StopwatchComponent) Body(context.Context) glint.Component {
return glint.Text(time.Now().Sub(c.start).Truncate(100 * time.Millisecond).String())
}

18
vendor/github.com/mitchellh/go-glint/context.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
package glint
// Context is a component type that can be used to set data on the context
// given to Body calls for components that are children of this component.
func Context(inner Component, kv ...interface{}) Component {
if len(kv)%2 != 0 {
panic("kv must be set in pairs")
}
return &contextComponent{inner: inner, pairs: kv}
}
type contextComponent struct {
terminalComponent
inner Component
pairs []interface{}
}

317
vendor/github.com/mitchellh/go-glint/document.go generated vendored Normal file
View File

@@ -0,0 +1,317 @@
package glint
import (
"context"
"io"
"os"
"sync"
"time"
"github.com/mitchellh/go-glint/flex"
)
// Document is the primary structure for managing and drawing components.
//
// A document represents a terminal window or session. The output can be set and
// components can be added, rendered, and drawn. All the methods on a Document
// are thread-safe unless otherwise documented. This allows you to draw,
// add components, replace components, etc. all while the render loop is active.
//
// Currently, this can only render directly to an io.Writer that expects to
// be a terminal session. In the future, we'll further abstract the concept
// of a "renderer" so that rendering can be done to other mediums as well.
type Document struct {
mu sync.Mutex
r Renderer
els []Component
refreshRate time.Duration
prevRoot *flex.Node
mounted map[ComponentMounter]struct{}
paused bool
closed bool
}
// New returns a Document that will output to stdout.
func New() *Document {
var d Document
d.SetRenderer(&TerminalRenderer{
Output: os.Stdout,
})
return &d
}
// SetRenderer sets the renderer to use. If this isn't set then Render
// will do nothing and return immediately. Changes to this will have no
// impact on active render loops.
func (d *Document) SetRenderer(r Renderer) {
d.mu.Lock()
defer d.mu.Unlock()
d.r = r
}
// SetRefreshRate sets the rate at which output is rendered.
func (d *Document) SetRefreshRate(dur time.Duration) {
d.mu.Lock()
defer d.mu.Unlock()
d.refreshRate = dur
}
// Append appends components to the document.
func (d *Document) Append(el ...Component) {
d.mu.Lock()
defer d.mu.Unlock()
d.els = append(d.els, el...)
}
// Set sets the components for the document. This will replace all
// previous components.
func (d *Document) Set(els ...Component) {
d.mu.Lock()
defer d.mu.Unlock()
d.els = els
}
// Close ensures that all elements are unmounted by finalizing all the
// output and then calling RenderFrame. Users of Document should ensure
// that Close is always called.
func (d *Document) Close() error {
d.mu.Lock()
if d.closed {
d.mu.Unlock()
return nil
}
for i, el := range d.els {
d.els[i] = Finalize(el)
}
d.closed = true
r := d.r
d.mu.Unlock()
// We call RenderFrame twice to ensure we remove the elements AND
// call Unmount on them.
d.RenderFrame()
d.RenderFrame()
// If our renderer implements closer then call close
if c, ok := r.(io.Closer); ok {
c.Close()
}
return nil
}
// Pause will pause the renderer. This will case RenderFrame to do nothing
// until Resume is called. The use case for this is if you want to wait for
// input (stdin) or any other reason.
func (d *Document) Pause() {
d.mu.Lock()
defer d.mu.Unlock()
d.paused = true
}
// Resume undoes a Pause call. If not paused, this does nothing.
func (d *Document) Resume() {
d.mu.Lock()
defer d.mu.Unlock()
d.paused = false
}
// Render starts a render loop that continues to render until the
// context is cancelled. This will render at the configured refresh rate.
// If the refresh rate is changed, it will not affect an active render loop.
// You must cancel and restart the render loop.
func (d *Document) Render(ctx context.Context) {
d.mu.Lock()
dur := d.refreshRate
d.mu.Unlock()
if dur == 0 {
dur = time.Second / 24
}
for {
// Render. We time the render so that we can adapt the framerate
// if the render is taking too long.
start := time.Now()
d.RenderFrame()
renderDur := time.Now().Sub(start)
// If our context is canceled, end.
if ctx.Err() != nil {
return
}
// If the duration is greater than our goal duration, then we
// adapt our duration. Otherwise, we sleep the duration we want
// and continue
sleepDur := dur
if renderDur > dur {
sleepDur = renderDur
// We slow our attempted framerate down at most to 1 fps
if sleepDur > 1*time.Second {
sleepDur = 1 * time.Second
}
}
time.Sleep(sleepDur)
}
}
// RenderFrame will render a single frame and return.
//
// If a manual size is not configured, this will recalcualte the window
// size on each call. This typically requires a syscall. This is a bit
// expensive but something we can optimize in the future if it ends up being
// a real source of FPS issues.
func (d *Document) RenderFrame() {
d.mu.Lock()
defer d.mu.Unlock()
// If we're paused do nothing.
if d.paused {
return
}
// If we don't have a renderer set, then don't render anything.
if d.r == nil {
return
}
// Our context
ctx := WithRenderer(context.Background(), d.r)
// Setup our root node
root := d.r.LayoutRoot()
// Build our render tree
tree(ctx, root, Fragment(d.els...), false)
// Calculate the layout
flex.CalculateLayout(root, flex.Undefined, flex.Undefined, flex.DirectionLTR)
// Fix any text nodes that need to be fixed.
d.handleNodes(ctx, root, nil)
// If the height of the root is zero then we do nothing.
if uint(root.LayoutGetHeight()) == 0 {
return
}
// Render the tree
d.r.RenderRoot(root, d.prevRoot)
// Store how much we drew
height := uint(root.LayoutGetHeight())
// If our component list is prefixed with finalized components, we
// prune these out and do not re-render them.
finalIdx := -1
for i, el := range d.els {
child := root.GetChild(i)
if child == nil {
break
}
// If the component is not finalized then we exit. If the
// component doesn't match our expectations it means we hit
// something weird and we exit too.
ctx, ok := child.Context.(*parentContext)
if !ok || ctx == nil || ctx.C != el || !ctx.Finalized {
break
}
// If this is finalized, then we have to subtract from the
// height the height of this child since we're not going to redraw.
// Then continue until we find one that isn't finalized.
height -= uint(child.LayoutGetHeight())
finalIdx = i
}
if finalIdx >= 0 {
// Change our elements
els := d.els[finalIdx+1:]
d.els = make([]Component, len(els))
copy(d.els, els)
// Reset the height on the root so that it reflects this change
root.Layout.Dimensions[flex.DimensionHeight] = float32(height)
}
// Store our previous root
d.prevRoot = root
}
func (d *Document) handleNodes(
ctx context.Context,
parent *flex.Node,
seen map[ComponentMounter]struct{},
) {
// For our first call, we detect the root since we use it later
// to do some final calls.
root := seen == nil
if root {
seen = map[ComponentMounter]struct{}{}
}
for _, child := range parent.Children {
if tctx, ok := child.Context.(treeContext); ok {
c := tctx.Component()
// Mount callbacks
if mc, ok := c.(ComponentMounter); ok {
// Only if we haven't seen this already...
if _, ok := seen[mc]; !ok {
seen[mc] = struct{}{}
if d.mounted == nil {
d.mounted = map[ComponentMounter]struct{}{}
}
// And we haven't notified this already...
if _, ok := d.mounted[mc]; !ok {
d.mounted[mc] = struct{}{}
// Notify
mc.Mount(ctx)
}
}
}
continue
}
// If the height/width that the layout engine calculated is less than
// the height that we originally measured, then we need to give the
// element a chance to rerender into that dimension.
if tctx, ok := child.Context.(*TextNodeContext); ok {
height := child.LayoutGetHeight()
width := child.LayoutGetWidth()
if height < tctx.Size.Height || width < tctx.Size.Width {
child.Measure(child,
width, flex.MeasureModeAtMost,
height, flex.MeasureModeAtMost,
)
}
}
d.handleNodes(ctx, child, seen)
}
// If we're the root call, then we preform some final calls. Otherwise
// we just return, we're done.
if !root {
return
}
// Go through our previously mounted set and if we didn't see it,
// then call unmount on it. After we're done, what we saw is our new
// map of mounted elements.
for mc := range d.mounted {
if _, ok := seen[mc]; !ok {
mc.Unmount(ctx)
}
}
d.mounted = seen
}

19
vendor/github.com/mitchellh/go-glint/finalize.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package glint
import "context"
// Finalize reutrns a component that will finalize the input component.
// See ComponentFinalizer for documentation on what finalization means.
func Finalize(c Component) Component {
return &finalizedComponent{
Component: c,
}
}
type finalizedComponent struct {
Component
}
func (c *finalizedComponent) Body(context.Context) Component {
return c.Component
}

31
vendor/github.com/mitchellh/go-glint/flex/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,31 @@
BSD License
For yoga software
Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
Copyright (c) 2017-present, Krzysztof Kowalczyk. 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 Facebook 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.

33
vendor/github.com/mitchellh/go-glint/flex/PATENTS generated vendored Normal file
View File

@@ -0,0 +1,33 @@
Additional Grant of Patent Rights Version 2
"Software" means the yoga software distributed by Facebook, Inc.
Facebook, Inc. (“Facebook”) hereby grants to each recipient of the Software
(“you”) a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
(subject to the termination provision below) license under any Necessary
Claims, to make, have made, use, sell, offer to sell, import, and otherwise
transfer the Software. For avoidance of doubt, no license is granted under
Facebook's rights in any patent claims that are infringed by (i) modifications
to the Software made by you or any third party or (ii) the Software in
combination with any software or other technology.
The license granted hereunder will terminate, automatically and without notice,
if you (or any of your subsidiaries, corporate affiliates or agents) initiate
directly or indirectly, or take a direct financial interest in, any Patent
Assertion: (i) against Facebook or any of its subsidiaries or corporate
affiliates, (ii) against any party if such Patent Assertion arises in whole or
in part from any software, technology, product or service of Facebook or any of
its subsidiaries or corporate affiliates, or (iii) against any party relating
to the Software. Notwithstanding the foregoing, if Facebook or any of its
subsidiaries or corporate affiliates files a lawsuit alleging patent
infringement against you in the first instance, and you respond by filing a
patent infringement counterclaim in that lawsuit against that party that is
unrelated to the Software, the license granted hereunder will not terminate
under section (i) of this paragraph due to such counterclaim.
A "Necessary Claim" is a claim of a patent owned by Facebook that is
necessarily infringed by the Software standing alone.
A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
or contributory infringement or inducement to infringe any patent, including a
cross-claim or counterclaim.

27
vendor/github.com/mitchellh/go-glint/flex/README.md generated vendored Normal file
View File

@@ -0,0 +1,27 @@
# flex - CSS flexbox layout implementation in Go
Go implementation of [flexbox CSS](https://www.w3.org/TR/css-flexbox-1/) layout algorithm.
A pure Go port of [Facebook's Yoga](https://github.com/facebook/yoga).
## How to use
Read [tutorial](https://blog.kowalczyk.info/article/9/tutorial-on-using-github.comkjkflex-go-package.html) or look at `_test.go` files.
## Status
The port is finished. The code works and passess all Yoga tests.
The API is awkward by Go standards but it's the best I could do given that I want to stay close to C version.
Logic is currently synced up to https://github.com/facebook/yoga/commit/f45059e1e696727c1282742b89d2c8bf06345254
## How the port was made
You can read a [detailed story](https://blog.kowalczyk.info/article/wN9R/experience-porting-4.5k-loc-of-c-to-go-facebooks-css-flexbox-implementation-yoga.html).
In short:
* manually ported [C code](https://github.com/facebook/yoga/tree/master/yoga) to Go, line-by-line
* manually ported [tests](https://github.com/facebook/yoga/tree/master/tests) to Go
* tweak the API from C style to be more Go like. The structure and logic still is very close to C code (this makes porting future C changes easy)

454
vendor/github.com/mitchellh/go-glint/flex/enums.go generated vendored Normal file
View File

@@ -0,0 +1,454 @@
package flex
// port of YGEnums.h
// Align describes align flex attribute
type Align int
const (
// AlignAuto is "auto"
AlignAuto Align = iota
// AlignFlexStart is "flex-start"
AlignFlexStart
// AlignCenter if "center"
AlignCenter
// AlignFlexEnd is "flex-end"
AlignFlexEnd
// AlignStretch is "strech"
AlignStretch
// AlignBaseline is "baseline"
AlignBaseline
// AlignSpaceBetween is "space-between"
AlignSpaceBetween
// AlignSpaceAround is "space-around"
AlignSpaceAround
)
// Dimension represents dimention
type Dimension int
const (
// DimensionWidth is width
DimensionWidth Dimension = iota
// DimensionHeight is height
DimensionHeight
)
// Direction represents right-to-left or left-to-right direction
type Direction int
const (
// DirectionInherit is "inherit"
DirectionInherit Direction = iota
// DirectionLTR is "ltr"
DirectionLTR
// DirectionRTL is "rtl"
DirectionRTL
)
// Display is "display" property
type Display int
const (
// DisplayFlex is "flex"
DisplayFlex Display = iota
// DisplayNone is "none"
DisplayNone
)
// Edge represents an edge
type Edge int
const (
// EdgeLeft is left edge
EdgeLeft Edge = iota
// EdgeTop is top edge
EdgeTop
// EdgeRight is right edge
EdgeRight
// EdgeBottom is bottom edge
EdgeBottom
// EdgeStart is start edge
EdgeStart
// EdgeEnd is end edge
EdgeEnd
// EdgeHorizontal is horizontal edge
EdgeHorizontal
// EdgeVertical is vertical edge
EdgeVertical
// EdgeAll is all edge
EdgeAll
)
const (
// EdgeCount is count of edges
EdgeCount = 9
)
// ExperimentalFeature defines experimental features
type ExperimentalFeature int
const (
// ExperimentalFeatureWebFlexBasis is web flex basis
ExperimentalFeatureWebFlexBasis ExperimentalFeature = iota
)
const (
experimentalFeatureCount = 1
)
// FlexDirection describes "flex-direction" property
type FlexDirection int
const (
// FlexDirectionColumn is "column"
FlexDirectionColumn FlexDirection = iota
// FlexDirectionColumnReverse is "column-reverse"
FlexDirectionColumnReverse
// FlexDirectionRow is "row"
FlexDirectionRow
// FlexDirectionRowReverse is "row-reverse"
FlexDirectionRowReverse
)
// Justify is "justify" property
type Justify int
const (
// JustifyFlexStart is "flex-start"
JustifyFlexStart Justify = iota
// JustifyCenter is "center"
JustifyCenter
// JustifyFlexEnd is "flex-end"
JustifyFlexEnd
// JustifySpaceBetween is "space-between"
JustifySpaceBetween
// JustifySpaceAround is "space-around"
JustifySpaceAround
)
// LogLevel represents log level
type LogLevel int
const (
LogLevelError LogLevel = iota
LogLevelWarn
LogLevelInfo
LogLevelDebug
LogLevelVerbose
LogLevelFatal
)
// MeasureMode defines measurement mode
type MeasureMode int
const (
// MeasureModeUndefined is undefined
MeasureModeUndefined MeasureMode = iota
// MeasureModeExactly is exactly
MeasureModeExactly
// MeasureModeAtMost is at-most
MeasureModeAtMost
)
const (
measureModeCount = 3
)
// NodeType defines node type
type NodeType int
const (
// NodeTypeDefault is default node
NodeTypeDefault NodeType = iota
// NodeTypeText is text node
NodeTypeText
)
// Overflow describes "overflow" property
type Overflow int
const (
// OverflowVisible is "visible"
OverflowVisible Overflow = iota
// OverflowHidden is "hidden"
OverflowHidden
// OverflowScroll is "scroll"
OverflowScroll
)
// PositionType is "position" property
type PositionType int
const (
// PositionTypeRelative is "relative"
PositionTypeRelative PositionType = iota
// PositionTypeAbsolute is "absolute"
PositionTypeAbsolute
)
type PrintOptions int
const (
PrintOptionsLayout PrintOptions = 1 << iota
PrintOptionsStyle
PrintOptionsChildren
)
// Unit is "unit" property
type Unit int
const (
// UnitUndefined is "undefined"
UnitUndefined Unit = iota
// UnitPoint is "point"
UnitPoint
// UnitPercent is "percent"
UnitPercent
// UnitAuto is "auto"
UnitAuto
)
// Wrap is "wrap" property
type Wrap int
const (
// WrapNoWrap is "no-wrap"
WrapNoWrap Wrap = iota
// WrapWrap is "wrap"
WrapWrap
// WrapWrapReverse is "reverse"
WrapWrapReverse
)
// AlignToString returns string version of Align enum
func AlignToString(value Align) string {
switch value {
case AlignAuto:
return "auto"
case AlignFlexStart:
return "flex-start"
case AlignCenter:
return "center"
case AlignFlexEnd:
return "flex-end"
case AlignStretch:
return "stretch"
case AlignBaseline:
return "baseline"
case AlignSpaceBetween:
return "space-between"
case AlignSpaceAround:
return "space-around"
}
return "unknown"
}
// DimensionToString returns string version of Dimension enum
func DimensionToString(value Dimension) string {
switch value {
case DimensionWidth:
return "width"
case DimensionHeight:
return "height"
}
return "unknown"
}
// DirectionToString returns string version of Direction enum
func DirectionToString(value Direction) string {
switch value {
case DirectionInherit:
return "inherit"
case DirectionLTR:
return "ltr"
case DirectionRTL:
return "rtl"
}
return "unknown"
}
// DisplayToString returns string version of Display enum
func DisplayToString(value Display) string {
switch value {
case DisplayFlex:
return "flex"
case DisplayNone:
return "none"
}
return "unknown"
}
// EdgeToString returns string version of Edge enum
func EdgeToString(value Edge) string {
switch value {
case EdgeLeft:
return "left"
case EdgeTop:
return "top"
case EdgeRight:
return "right"
case EdgeBottom:
return "bottom"
case EdgeStart:
return "start"
case EdgeEnd:
return "end"
case EdgeHorizontal:
return "horizontal"
case EdgeVertical:
return "vertical"
case EdgeAll:
return "all"
}
return "unknown"
}
// ExperimentalFeatureToString returns string version of ExperimentalFeature enum
func ExperimentalFeatureToString(value ExperimentalFeature) string {
switch value {
case ExperimentalFeatureWebFlexBasis:
return "web-flex-basis"
}
return "unknown"
}
// FlexDirectionToString returns string version of FlexDirection enum
func FlexDirectionToString(value FlexDirection) string {
switch value {
case FlexDirectionColumn:
return "column"
case FlexDirectionColumnReverse:
return "column-reverse"
case FlexDirectionRow:
return "row"
case FlexDirectionRowReverse:
return "row-reverse"
}
return "unknown"
}
// JustifyToString returns string version of Justify enum
func JustifyToString(value Justify) string {
switch value {
case JustifyFlexStart:
return "flex-start"
case JustifyCenter:
return "center"
case JustifyFlexEnd:
return "flex-end"
case JustifySpaceBetween:
return "space-between"
case JustifySpaceAround:
return "space-around"
}
return "unknown"
}
// LogLevelToString returns string version of LogLevel enum
func LogLevelToString(value LogLevel) string {
switch value {
case LogLevelError:
return "error"
case LogLevelWarn:
return "warn"
case LogLevelInfo:
return "info"
case LogLevelDebug:
return "debug"
case LogLevelVerbose:
return "verbose"
case LogLevelFatal:
return "fatal"
}
return "unknown"
}
// MeasureModeToString returns string version of MeasureMode enum
func MeasureModeToString(value MeasureMode) string {
switch value {
case MeasureModeUndefined:
return "undefined"
case MeasureModeExactly:
return "exactly"
case MeasureModeAtMost:
return "at-most"
}
return "unknown"
}
// NodeTypeToString returns string version of NodeType enum
func NodeTypeToString(value NodeType) string {
switch value {
case NodeTypeDefault:
return "default"
case NodeTypeText:
return "text"
}
return "unknown"
}
// OverflowToString returns string version of Overflow enum
func OverflowToString(value Overflow) string {
switch value {
case OverflowVisible:
return "visible"
case OverflowHidden:
return "hidden"
case OverflowScroll:
return "scroll"
}
return "unknown"
}
// PositionTypeToString returns string version of PositionType enum
func PositionTypeToString(value PositionType) string {
switch value {
case PositionTypeRelative:
return "relative"
case PositionTypeAbsolute:
return "absolute"
}
return "unknown"
}
// PrintOptionsToString returns string version of PrintOptions enum
func PrintOptionsToString(value PrintOptions) string {
switch value {
case PrintOptionsLayout:
return "layout"
case PrintOptionsStyle:
return "style"
case PrintOptionsChildren:
return "children"
}
return "unknown"
}
// UnitToString returns string version of Unit enum
func UnitToString(value Unit) string {
switch value {
case UnitUndefined:
return "undefined"
case UnitPoint:
return "point"
case UnitPercent:
return "percent"
case UnitAuto:
return "auto"
}
return "unknown"
}
// WrapToString returns string version of Wrap enum
func WrapToString(value Wrap) string {
switch value {
case WrapNoWrap:
return "no-wrap"
case WrapWrap:
return "wrap"
case WrapWrapReverse:
return "wrap-reverse"
}
return "unknown"
}

73
vendor/github.com/mitchellh/go-glint/flex/math.go generated vendored Normal file
View File

@@ -0,0 +1,73 @@
package flex
import "math"
// from https://github.com/rkusa/gm/blob/master/math32/bits.go
const (
uvnan = 0x7FC00001
)
var (
NAN = math.Float32frombits(uvnan)
)
// NaN returns an IEEE 754 ``not-a-number'' value.
func NaN() float32 { return math.Float32frombits(uvnan) }
// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value.
func IsNaN(f float32) (is bool) {
return f != f
}
func feq(a, b float32) bool {
if IsNaN(a) && IsNaN(b) {
return true
}
return a == b
}
// https://github.com/evanphx/ulysses-libc/blob/master/src/math/fmaxf.c
func fmaxf(a float32, b float32) float32 {
if IsNaN(a) {
return b
}
if IsNaN(b) {
return a
}
// TODO: signed zeros
if a > b {
return a
}
return b
}
// https://github.com/evanphx/ulysses-libc/blob/master/src/math/fminf.c
func fminf(a float32, b float32) float32 {
if IsNaN(a) {
return b
}
if IsNaN(b) {
return a
}
// TODO: signed zeros
if a < b {
return a
}
return b
}
func fabs(x float32) float32 {
switch {
case x < 0:
return -x
case x == 0:
return 0 // return correctly abs(-0)
}
return x
}
func fmodf(x, y float32) float32 {
res := math.Mod(float64(x), float64(y))
return float32(res)
}

199
vendor/github.com/mitchellh/go-glint/flex/print.go generated vendored Normal file
View File

@@ -0,0 +1,199 @@
package flex
import (
"fmt"
"io"
"os"
"strings"
)
// NodePrinter node printer.
type NodePrinter struct {
writer io.Writer
options PrintOptions
}
// NodePrint prints node to standard output.
func NodePrint(node *Node, options PrintOptions) {
printer := NewNodePrinter(os.Stdout, options)
printer.Print(node)
}
// NewNodePrinter creates new node printer.
func NewNodePrinter(writer io.Writer, options PrintOptions) *NodePrinter {
return &NodePrinter{
writer: writer,
options: options,
}
}
// Print prints node.
func (printer *NodePrinter) Print(node *Node) {
printer.printNode(node, 0)
}
func (printer *NodePrinter) printNode(node *Node, level int) {
printer.printIndent(level)
printer.printf("<div ")
if node.Print != nil {
node.Print(node)
}
if printer.options&PrintOptionsLayout != 0 {
printer.printf("layout=\"")
printer.printf("width: %g; ", node.Layout.Dimensions[DimensionWidth])
printer.printf("height: %g; ", node.Layout.Dimensions[DimensionHeight])
printer.printf("top: %g; ", node.Layout.Position[EdgeTop])
printer.printf("left: %g;", node.Layout.Position[EdgeLeft])
printer.printf("\" ")
}
if printer.options&PrintOptionsStyle != 0 {
printer.printf("style=\"")
if node.Style.FlexDirection != nodeDefaults.Style.FlexDirection {
printer.printf("flex-direction: %s; ",
FlexDirectionToString(node.Style.FlexDirection))
}
if node.Style.JustifyContent != nodeDefaults.Style.JustifyContent {
printer.printf("justify-content: %s; ",
JustifyToString(node.Style.JustifyContent))
}
if node.Style.AlignItems != nodeDefaults.Style.AlignItems {
printer.printf("align-items: %s; ", AlignToString(node.Style.AlignItems))
}
if node.Style.AlignContent != nodeDefaults.Style.AlignContent {
printer.printf("align-content: %s; ", AlignToString(node.Style.AlignContent))
}
if node.Style.AlignSelf != nodeDefaults.Style.AlignSelf {
printer.printf("align-self: %s; ", AlignToString(node.Style.AlignSelf))
}
printer.printFloatIfNotUndefined(node, "flex-grow", node.Style.FlexGrow)
printer.printFloatIfNotUndefined(node, "flex-shrink", node.Style.FlexShrink)
printer.printNumberIfNotAuto(node, "flex-basis", &node.Style.FlexBasis)
printer.printFloatIfNotUndefined(node, "flex", node.Style.Flex)
if node.Style.FlexWrap != nodeDefaults.Style.FlexWrap {
printer.printf("flexWrap: %s; ", WrapToString(node.Style.FlexWrap))
}
if node.Style.Overflow != nodeDefaults.Style.Overflow {
printer.printf("overflow: %s; ", OverflowToString(node.Style.Overflow))
}
if node.Style.Display != nodeDefaults.Style.Display {
printer.printf("display: %s; ", DisplayToString(node.Style.Display))
}
printer.printEdges(node, "margin", node.Style.Margin[:])
printer.printEdges(node, "padding", node.Style.Padding[:])
printer.printEdges(node, "border", node.Style.Border[:])
printer.printNumberIfNotAuto(node, "width", &node.Style.Dimensions[DimensionWidth])
printer.printNumberIfNotAuto(node, "height", &node.Style.Dimensions[DimensionHeight])
printer.printNumberIfNotAuto(node, "max-width", &node.Style.MaxDimensions[DimensionWidth])
printer.printNumberIfNotAuto(node, "max-height", &node.Style.MaxDimensions[DimensionHeight])
printer.printNumberIfNotAuto(node, "min-width", &node.Style.MinDimensions[DimensionWidth])
printer.printNumberIfNotAuto(node, "min-height", &node.Style.MinDimensions[DimensionHeight])
if node.Style.PositionType != nodeDefaults.Style.PositionType {
printer.printf("position: %s; ",
PositionTypeToString(node.Style.PositionType))
}
printer.printEdgeIfNotUndefined(node, "left", node.Style.Position[:], EdgeLeft)
printer.printEdgeIfNotUndefined(node, "right", node.Style.Position[:], EdgeRight)
printer.printEdgeIfNotUndefined(node, "top", node.Style.Position[:], EdgeTop)
printer.printEdgeIfNotUndefined(node, "bottom", node.Style.Position[:], EdgeBottom)
printer.printf("\"")
if node.Measure != nil {
printer.printf(" has-custom-measure=\"true\"")
}
}
printer.printf(">")
childCount := len(node.Children)
if printer.options&PrintOptionsChildren != 0 && childCount > 0 {
for i := 0; i < childCount; i++ {
printer.printf("\n")
printer.printNode(node.Children[i], level+1)
}
printer.printIndent(level)
printer.printf("\n")
}
if childCount != 0 {
printer.printIndent(level)
}
printer.printf("</div>")
}
func (printer *NodePrinter) printEdges(node *Node, str string, edges []Value) {
if fourValuesEqual(edges) {
printer.printNumberIfNotZero(node, str, &edges[EdgeLeft])
// bugfix for issue #5
// if we set EdgeAll, the values are
// [{NaN 0} {NaN 0} {NaN 0} {NaN 0} {NaN 0} {NaN 0} {NaN 0} {NaN 0} {20 1}]
// so EdgeLeft is not printed and we won't print padding
// for simplicity, I assume that EdgeAll is exclusive with setting specific edges
// so we can print both and only one should show up
// C code has this bug: https://github.com/facebook/yoga/blob/26481a6553a33d9c005f2b8d24a7952fc58df32c/yoga/Yoga.c#L1036
printer.printNumberIfNotZero(node, str, &edges[EdgeAll])
} else {
for edge := EdgeLeft; edge < EdgeCount; edge++ {
buf := fmt.Sprintf("%s-%s", str, EdgeToString(edge))
printer.printNumberIfNotZero(node, buf, &edges[edge])
}
}
}
func (printer *NodePrinter) printEdgeIfNotUndefined(node *Node, str string, edges []Value, edge Edge) {
printer.printNumberIfNotUndefined(node, str, computedEdgeValue(edges, edge, &ValueUndefined))
}
func (printer *NodePrinter) printFloatIfNotUndefined(node *Node, str string, number float32) {
if !FloatIsUndefined(number) {
printer.printf("%s: %g; ", str, number)
}
}
func (printer *NodePrinter) printNumberIfNotUndefined(node *Node, str string, number *Value) {
if number.Unit != UnitUndefined {
if number.Unit == UnitAuto {
printer.printf("%s: auto; ", str)
} else {
unit := "%"
if number.Unit == UnitPoint {
unit = "px"
}
printer.printf("%s: %g%s; ", str, number.Value, unit)
}
}
}
func (printer *NodePrinter) printNumberIfNotAuto(node *Node, str string, number *Value) {
if number.Unit != UnitAuto {
printer.printNumberIfNotUndefined(node, str, number)
}
}
func (printer *NodePrinter) printNumberIfNotZero(node *Node, str string, number *Value) {
if !FloatsEqual(number.Value, 0) {
printer.printNumberIfNotUndefined(node, str, number)
}
}
func (printer *NodePrinter) printf(format string, args ...interface{}) {
fmt.Fprintf(printer.writer, format, args...)
}
func (printer *NodePrinter) printIndent(n int) {
printer.writer.Write([]byte(strings.Repeat(" ", n)))
}
func fourValuesEqual(four []Value) bool {
return ValueEqual(four[0], four[1]) && ValueEqual(four[0], four[2]) &&
ValueEqual(four[0], four[3])
}

3080
vendor/github.com/mitchellh/go-glint/flex/yoga.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

37
vendor/github.com/mitchellh/go-glint/flex/yoga_h.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package flex
var (
// Undefined defines undefined value
Undefined = NAN
)
// Size describes size
type Size struct {
Width float32
Height float32
}
// Value describes value
type Value struct {
Value float32
Unit Unit
}
var (
// ValueUndefined defines undefined YGValue
ValueUndefined = Value{Undefined, UnitUndefined}
// ValueAuto defines auto YGValue
ValueAuto = Value{Undefined, UnitAuto}
)
// MeasureFunc describes function for measuring
type MeasureFunc func(node *Node, width float32, widthMode MeasureMode, height float32, heightMode MeasureMode) Size
// BaselineFunc describes function for baseline
type BaselineFunc func(node *Node, width float32, height float32) float32
// PrintFunc defines function for printing
type PrintFunc func(node *Node)
// Logger defines logging function
type Logger func(config *Config, node *Node, level LogLevel, format string, args ...interface{}) int

615
vendor/github.com/mitchellh/go-glint/flex/yoga_props.go generated vendored Normal file
View File

@@ -0,0 +1,615 @@
package flex
/*
Functions that get/set props, in C code generated from those C macros:
YG_NODE_PROPERTY_IMPL(void *, Context, context, context);
YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print);
YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout);
YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType);
YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction);
YG_NODE_STYLE_PROPERTY_IMPL(YGFlexDirection, FlexDirection, flexDirection, flexDirection);
YG_NODE_STYLE_PROPERTY_IMPL(YGJustify, JustifyContent, justifyContent, justifyContent);
YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent);
YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems);
YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf);
YG_NODE_STYLE_PROPERTY_IMPL(YGPositionType, PositionType, positionType, positionType);
YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap);
YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow);
YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display);
YG_NODE_STYLE_PROPERTY_IMPL(float, Flex, flex, flex);
YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexGrow, flexGrow, flexGrow);
YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexShrink, flexShrink, flexShrink);
YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, FlexBasis, flexBasis, flexBasis);
YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Position, position, position);
YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Margin, margin, margin);
YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Margin, margin);
YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Padding, padding, padding);
YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border);
YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]);
YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]);
YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]);
YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]);
YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]);
YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]);
// Yoga specific properties, not compatible with flexbox specification
YG_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]);
YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]);
YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction);
YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow);
YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin);
YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border);
YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding);
*/
// StyleSetWidth sets width
func (node *Node) StyleSetWidth(width float32) {
dim := &node.Style.Dimensions[DimensionWidth]
if dim.Value != width || dim.Unit != UnitPoint {
dim.Value = width
dim.Unit = UnitPoint
if FloatIsUndefined(width) {
dim.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetWidthPercent sets width percent
func (node *Node) StyleSetWidthPercent(width float32) {
dim := &node.Style.Dimensions[DimensionWidth]
if dim.Value != width || dim.Unit != UnitPercent {
dim.Value = width
dim.Unit = UnitPercent
if FloatIsUndefined(width) {
dim.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetWidthAuto sets width auto
func (node *Node) StyleSetWidthAuto() {
dim := &node.Style.Dimensions[DimensionWidth]
if dim.Unit != UnitAuto {
dim.Value = Undefined
dim.Unit = UnitAuto
nodeMarkDirtyInternal(node)
}
}
// StyleGetWidth gets width
func (node *Node) StyleGetWidth() Value {
return node.Style.Dimensions[DimensionWidth]
}
// StyleSetHeight sets height
func (node *Node) StyleSetHeight(height float32) {
dim := &node.Style.Dimensions[DimensionHeight]
if dim.Value != height || dim.Unit != UnitPoint {
dim.Value = height
dim.Unit = UnitPoint
if FloatIsUndefined(height) {
dim.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetHeightPercent sets height percent
func (node *Node) StyleSetHeightPercent(height float32) {
dim := &node.Style.Dimensions[DimensionHeight]
if dim.Value != height || dim.Unit != UnitPercent {
dim.Value = height
dim.Unit = UnitPercent
if FloatIsUndefined(height) {
dim.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetHeightAuto sets height auto
func (node *Node) StyleSetHeightAuto() {
dim := &node.Style.Dimensions[DimensionHeight]
if dim.Unit != UnitAuto {
dim.Value = Undefined
dim.Unit = UnitAuto
nodeMarkDirtyInternal(node)
}
}
// StyleGetHeight gets height
func (node *Node) StyleGetHeight() Value {
return node.Style.Dimensions[DimensionHeight]
}
// StyleSetPositionType sets position type
func (node *Node) StyleSetPositionType(positionType PositionType) {
if node.Style.PositionType != positionType {
node.Style.PositionType = positionType
nodeMarkDirtyInternal(node)
}
}
// StyleSetPosition sets position
func (node *Node) StyleSetPosition(edge Edge, position float32) {
pos := &node.Style.Position[edge]
if pos.Value != position || pos.Unit != UnitPoint {
pos.Value = position
pos.Unit = UnitPoint
if FloatIsUndefined(position) {
pos.Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetPositionPercent sets position percent
func (node *Node) StyleSetPositionPercent(edge Edge, position float32) {
pos := &node.Style.Position[edge]
if pos.Value != position || pos.Unit != UnitPercent {
pos.Value = position
pos.Unit = UnitPercent
if FloatIsUndefined(position) {
pos.Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetPosition gets position
func (node *Node) StyleGetPosition(edge Edge) Value {
return node.Style.Position[edge]
}
// StyleSetDirection sets direction
func (node *Node) StyleSetDirection(direction Direction) {
if node.Style.Direction != direction {
node.Style.Direction = direction
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexDirection sets flex directions
func (node *Node) StyleSetFlexDirection(flexDirection FlexDirection) {
if node.Style.FlexDirection != flexDirection {
node.Style.FlexDirection = flexDirection
nodeMarkDirtyInternal(node)
}
}
// StyleSetJustifyContent sets justify content
func (node *Node) StyleSetJustifyContent(justifyContent Justify) {
if node.Style.JustifyContent != justifyContent {
node.Style.JustifyContent = justifyContent
nodeMarkDirtyInternal(node)
}
}
// StyleSetAlignContent sets align content
func (node *Node) StyleSetAlignContent(alignContent Align) {
if node.Style.AlignContent != alignContent {
node.Style.AlignContent = alignContent
nodeMarkDirtyInternal(node)
}
}
// StyleSetAlignItems sets align content
func (node *Node) StyleSetAlignItems(alignItems Align) {
if node.Style.AlignItems != alignItems {
node.Style.AlignItems = alignItems
nodeMarkDirtyInternal(node)
}
}
// StyleSetAlignSelf sets align self
func (node *Node) StyleSetAlignSelf(alignSelf Align) {
if node.Style.AlignSelf != alignSelf {
node.Style.AlignSelf = alignSelf
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexWrap sets flex wrap
func (node *Node) StyleSetFlexWrap(flexWrap Wrap) {
if node.Style.FlexWrap != flexWrap {
node.Style.FlexWrap = flexWrap
nodeMarkDirtyInternal(node)
}
}
// StyleSetOverflow sets overflow
func (node *Node) StyleSetOverflow(overflow Overflow) {
if node.Style.Overflow != overflow {
node.Style.Overflow = overflow
nodeMarkDirtyInternal(node)
}
}
// StyleSetDisplay sets display
func (node *Node) StyleSetDisplay(display Display) {
if node.Style.Display != display {
node.Style.Display = display
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlex sets flex
func (node *Node) StyleSetFlex(flex float32) {
if node.Style.Flex != flex {
node.Style.Flex = flex
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexGrow sets flex grow
func (node *Node) StyleSetFlexGrow(flexGrow float32) {
if node.Style.FlexGrow != flexGrow {
node.Style.FlexGrow = flexGrow
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexShrink sets flex shrink
func (node *Node) StyleSetFlexShrink(flexShrink float32) {
if node.Style.FlexShrink != flexShrink {
node.Style.FlexShrink = flexShrink
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexBasis sets flex basis
func (node *Node) StyleSetFlexBasis(flexBasis float32) {
if node.Style.FlexBasis.Value != flexBasis ||
node.Style.FlexBasis.Unit != UnitPoint {
node.Style.FlexBasis.Value = flexBasis
node.Style.FlexBasis.Unit = UnitPoint
if FloatIsUndefined(flexBasis) {
node.Style.FlexBasis.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetFlexBasisPercent sets flex basis percent
func (node *Node) StyleSetFlexBasisPercent(flexBasis float32) {
if node.Style.FlexBasis.Value != flexBasis ||
node.Style.FlexBasis.Unit != UnitPercent {
node.Style.FlexBasis.Value = flexBasis
node.Style.FlexBasis.Unit = UnitPercent
if FloatIsUndefined(flexBasis) {
node.Style.FlexBasis.Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// NodeStyleSetFlexBasisAuto sets flex basis auto
func NodeStyleSetFlexBasisAuto(node *Node) {
if node.Style.FlexBasis.Unit != UnitAuto {
node.Style.FlexBasis.Value = Undefined
node.Style.FlexBasis.Unit = UnitAuto
nodeMarkDirtyInternal(node)
}
}
// StyleSetMargin sets margin
func (node *Node) StyleSetMargin(edge Edge, margin float32) {
if node.Style.Margin[edge].Value != margin ||
node.Style.Margin[edge].Unit != UnitPoint {
node.Style.Margin[edge].Value = margin
node.Style.Margin[edge].Unit = UnitPoint
if FloatIsUndefined(margin) {
node.Style.Margin[edge].Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetMarginPercent sets margin percent
func (node *Node) StyleSetMarginPercent(edge Edge, margin float32) {
if node.Style.Margin[edge].Value != margin ||
node.Style.Margin[edge].Unit != UnitPercent {
node.Style.Margin[edge].Value = margin
node.Style.Margin[edge].Unit = UnitPercent
if FloatIsUndefined(margin) {
node.Style.Margin[edge].Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetMargin gets margin
func (node *Node) StyleGetMargin(edge Edge) Value {
return node.Style.Margin[edge]
}
// StyleSetMarginAuto sets margin auto
func (node *Node) StyleSetMarginAuto(edge Edge) {
if node.Style.Margin[edge].Unit != UnitAuto {
node.Style.Margin[edge].Value = Undefined
node.Style.Margin[edge].Unit = UnitAuto
nodeMarkDirtyInternal(node)
}
}
// StyleSetPadding sets padding
func (node *Node) StyleSetPadding(edge Edge, padding float32) {
if node.Style.Padding[edge].Value != padding ||
node.Style.Padding[edge].Unit != UnitPoint {
node.Style.Padding[edge].Value = padding
node.Style.Padding[edge].Unit = UnitPoint
if FloatIsUndefined(padding) {
node.Style.Padding[edge].Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetPaddingPercent sets padding percent
func (node *Node) StyleSetPaddingPercent(edge Edge, padding float32) {
if node.Style.Padding[edge].Value != padding ||
node.Style.Padding[edge].Unit != UnitPercent {
node.Style.Padding[edge].Value = padding
node.Style.Padding[edge].Unit = UnitPercent
if FloatIsUndefined(padding) {
node.Style.Padding[edge].Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetPadding gets padding
func (node *Node) StyleGetPadding(edge Edge) Value {
return node.Style.Padding[edge]
}
// StyleSetBorder sets border
func (node *Node) StyleSetBorder(edge Edge, border float32) {
if node.Style.Border[edge].Value != border ||
node.Style.Border[edge].Unit != UnitPoint {
node.Style.Border[edge].Value = border
node.Style.Border[edge].Unit = UnitPoint
if FloatIsUndefined(border) {
node.Style.Border[edge].Unit = UnitUndefined
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetBorder gets border
func (node *Node) StyleGetBorder(edge Edge) float32 {
return node.Style.Border[edge].Value
}
// StyleSetMinWidth sets min width
func (node *Node) StyleSetMinWidth(minWidth float32) {
if node.Style.MinDimensions[DimensionWidth].Value != minWidth ||
node.Style.MinDimensions[DimensionWidth].Unit != UnitPoint {
node.Style.MinDimensions[DimensionWidth].Value = minWidth
node.Style.MinDimensions[DimensionWidth].Unit = UnitPoint
if FloatIsUndefined(minWidth) {
node.Style.MinDimensions[DimensionWidth].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetMinWidthPercent sets width percent
func (node *Node) StyleSetMinWidthPercent(minWidth float32) {
if node.Style.MinDimensions[DimensionWidth].Value != minWidth ||
node.Style.MinDimensions[DimensionWidth].Unit != UnitPercent {
node.Style.MinDimensions[DimensionWidth].Value = minWidth
node.Style.MinDimensions[DimensionWidth].Unit = UnitPercent
if FloatIsUndefined(minWidth) {
node.Style.MinDimensions[DimensionWidth].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetMinWidth gets min width
func (node *Node) StyleGetMinWidth() Value {
return node.Style.MinDimensions[DimensionWidth]
}
// StyleSetMinHeight sets min width
func (node *Node) StyleSetMinHeight(minHeight float32) {
if node.Style.MinDimensions[DimensionHeight].Value != minHeight ||
node.Style.MinDimensions[DimensionHeight].Unit != UnitPoint {
node.Style.MinDimensions[DimensionHeight].Value = minHeight
node.Style.MinDimensions[DimensionHeight].Unit = UnitPoint
if FloatIsUndefined(minHeight) {
node.Style.MinDimensions[DimensionHeight].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetMinHeightPercent sets min height percent
func (node *Node) StyleSetMinHeightPercent(minHeight float32) {
if node.Style.MinDimensions[DimensionHeight].Value != minHeight ||
node.Style.MinDimensions[DimensionHeight].Unit != UnitPercent {
node.Style.MinDimensions[DimensionHeight].Value = minHeight
node.Style.MinDimensions[DimensionHeight].Unit = UnitPercent
if FloatIsUndefined(minHeight) {
node.Style.MinDimensions[DimensionHeight].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetMinHeight gets min height
func (node *Node) StyleGetMinHeight() Value {
return node.Style.MinDimensions[DimensionHeight]
}
// StyleSetMaxWidth sets max width
func (node *Node) StyleSetMaxWidth(maxWidth float32) {
if node.Style.MaxDimensions[DimensionWidth].Value != maxWidth ||
node.Style.MaxDimensions[DimensionWidth].Unit != UnitPoint {
node.Style.MaxDimensions[DimensionWidth].Value = maxWidth
node.Style.MaxDimensions[DimensionWidth].Unit = UnitPoint
if FloatIsUndefined(maxWidth) {
node.Style.MaxDimensions[DimensionWidth].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetMaxWidthPercent sets max width percent
func (node *Node) StyleSetMaxWidthPercent(maxWidth float32) {
if node.Style.MaxDimensions[DimensionWidth].Value != maxWidth ||
node.Style.MaxDimensions[DimensionWidth].Unit != UnitPercent {
node.Style.MaxDimensions[DimensionWidth].Value = maxWidth
node.Style.MaxDimensions[DimensionWidth].Unit = UnitPercent
if FloatIsUndefined(maxWidth) {
node.Style.MaxDimensions[DimensionWidth].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetMaxWidth gets max width
func (node *Node) StyleGetMaxWidth() Value {
return node.Style.MaxDimensions[DimensionWidth]
}
// StyleSetMaxHeight sets max width
func (node *Node) StyleSetMaxHeight(maxHeight float32) {
if node.Style.MaxDimensions[DimensionHeight].Value != maxHeight ||
node.Style.MaxDimensions[DimensionHeight].Unit != UnitPoint {
node.Style.MaxDimensions[DimensionHeight].Value = maxHeight
node.Style.MaxDimensions[DimensionHeight].Unit = UnitPoint
if FloatIsUndefined(maxHeight) {
node.Style.MaxDimensions[DimensionHeight].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleSetMaxHeightPercent sets max height percent
func (node *Node) StyleSetMaxHeightPercent(maxHeight float32) {
if node.Style.MaxDimensions[DimensionHeight].Value != maxHeight ||
node.Style.MaxDimensions[DimensionHeight].Unit != UnitPercent {
node.Style.MaxDimensions[DimensionHeight].Value = maxHeight
node.Style.MaxDimensions[DimensionHeight].Unit = UnitPercent
if FloatIsUndefined(maxHeight) {
node.Style.MaxDimensions[DimensionHeight].Unit = UnitAuto
}
nodeMarkDirtyInternal(node)
}
}
// StyleGetMaxHeight gets max height
func (node *Node) StyleGetMaxHeight() Value {
return node.Style.MaxDimensions[DimensionHeight]
}
// StyleSetAspectRatio sets axpect ratio
func (node *Node) StyleSetAspectRatio(aspectRatio float32) {
if node.Style.AspectRatio != aspectRatio {
node.Style.AspectRatio = aspectRatio
nodeMarkDirtyInternal(node)
}
}
// LayoutGetLeft gets left
func (node *Node) LayoutGetLeft() float32 {
return node.Layout.Position[EdgeLeft]
}
// LayoutGetTop gets top
func (node *Node) LayoutGetTop() float32 {
return node.Layout.Position[EdgeTop]
}
// LayoutGetRight gets right
func (node *Node) LayoutGetRight() float32 {
return node.Layout.Position[EdgeRight]
}
// LayoutGetBottom gets bottom
func (node *Node) LayoutGetBottom() float32 {
return node.Layout.Position[EdgeBottom]
}
// LayoutGetWidth gets width
func (node *Node) LayoutGetWidth() float32 {
return node.Layout.Dimensions[DimensionWidth]
}
// LayoutGetHeight gets height
func (node *Node) LayoutGetHeight() float32 {
return node.Layout.Dimensions[DimensionHeight]
}
// LayoutGetMargin gets margin
func (node *Node) LayoutGetMargin(edge Edge) float32 {
assertWithNode(node, edge < EdgeEnd, "Cannot get layout properties of multi-edge shorthands")
if edge == EdgeLeft {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Margin[EdgeEnd]
}
return node.Layout.Margin[EdgeStart]
}
if edge == EdgeRight {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Margin[EdgeStart]
}
return node.Layout.Margin[EdgeEnd]
}
return node.Layout.Margin[edge]
}
// LayoutGetBorder gets border
func (node *Node) LayoutGetBorder(edge Edge) float32 {
assertWithNode(node, edge < EdgeEnd,
"Cannot get layout properties of multi-edge shorthands")
if edge == EdgeLeft {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Border[EdgeEnd]
}
return node.Layout.Border[EdgeStart]
}
if edge == EdgeRight {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Border[EdgeStart]
}
return node.Layout.Border[EdgeEnd]
}
return node.Layout.Border[edge]
}
// LayoutGetPadding gets padding
func (node *Node) LayoutGetPadding(edge Edge) float32 {
assertWithNode(node, edge < EdgeEnd,
"Cannot get layout properties of multi-edge shorthands")
if edge == EdgeLeft {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Padding[EdgeEnd]
}
return node.Layout.Padding[EdgeStart]
}
if edge == EdgeRight {
if node.Layout.Direction == DirectionRTL {
return node.Layout.Padding[EdgeStart]
}
return node.Layout.Padding[EdgeEnd]
}
return node.Layout.Padding[edge]
}

14
vendor/github.com/mitchellh/go-glint/fragment.go generated vendored Normal file
View File

@@ -0,0 +1,14 @@
package glint
// Fragment appends multiple components together. A fragment has no layout
// implications, it is as if the set of components were appended directly to
// the parent.
func Fragment(c ...Component) Component {
return &fragmentComponent{List: c}
}
type fragmentComponent struct {
terminalComponent
List []Component
}

15
vendor/github.com/mitchellh/go-glint/go.mod generated vendored Normal file
View File

@@ -0,0 +1,15 @@
module github.com/mitchellh/go-glint
go 1.14
require (
github.com/cheggaaa/pb/v3 v3.0.5
github.com/containerd/console v1.0.1
github.com/gookit/color v1.3.1
github.com/mitchellh/go-testing-interface v1.14.1
github.com/mitchellh/go-wordwrap v1.0.1
github.com/morikuni/aec v1.0.0
github.com/stretchr/testify v1.6.1
github.com/tj/go-spin v1.1.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
)

51
vendor/github.com/mitchellh/go-glint/go.sum generated vendored Normal file
View File

@@ -0,0 +1,51 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE=
github.com/cheggaaa/pb/v3 v3.0.5/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw=
github.com/containerd/console v1.0.1 h1:u7SFAJyRqWcG6ogaMAx3KjSTy1e3hT9QxqX7Jco7dRc=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/gookit/color v1.3.1 h1:PPD/C7sf8u2L8XQPdPgsWRoAiLQGZEZOzU3cf5IYYUk=
github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds=
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f h1:6Sc1XOXTulBN6imkqo6XoAXDEzoQ4/ro6xy7Vn8+rOM=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,42 @@
package layout
import (
"github.com/mitchellh/go-glint/flex"
)
type SetFunc func(n *flex.Node)
// Builder builds a set of styles to apply to a flex node.
type Builder struct {
f SetFunc
}
// Raw composes a SetFunc on the builder. This will call the previous
// styles setters first and then call this function.
func (l *Builder) Raw(f SetFunc) *Builder {
return l.add(f)
}
// Apply sets the styles on the flex node.
func (l *Builder) Apply(node *flex.Node) {
if l == nil || l.f == nil {
return
}
l.f(node)
}
// add is a helper to add the function to the call chain for this builder.
// This will return a new builder.
func (l *Builder) add(f func(*flex.Node)) *Builder {
old := l.f
new := func(n *flex.Node) {
if old != nil {
old(n)
}
f(n)
}
return &Builder{f: new}
}

72
vendor/github.com/mitchellh/go-glint/layout.go generated vendored Normal file
View File

@@ -0,0 +1,72 @@
package glint
import (
"context"
"github.com/mitchellh/go-glint/flex"
"github.com/mitchellh/go-glint/internal/layout"
)
// Layout is used to set layout properties for the child components.
// This can be used similarly to a "div" in HTML with "display: flex" set.
// This component follows the builder pattern for setting layout properties
// such as margins, paddings, etc.
func Layout(inner ...Component) *LayoutComponent {
return &LayoutComponent{inner: inner, builder: &layout.Builder{}}
}
// LayoutComponent is a component used for layout settings. See Layout.
type LayoutComponent struct {
inner []Component
builder *layout.Builder
}
// Row sets the `flex-direction: row` property.
func (c *LayoutComponent) Row() *LayoutComponent {
c.builder = c.builder.Raw(func(n *flex.Node) {
n.StyleSetFlexDirection(flex.FlexDirectionRow)
})
return c
}
// MarginLeft sets the `margin-left` property.
func (c *LayoutComponent) MarginLeft(x int) *LayoutComponent {
c.builder = c.builder.Raw(func(n *flex.Node) {
n.StyleSetMargin(flex.EdgeLeft, float32(x))
})
return c
}
// MarginRight sets the `margin-left` property.
func (c *LayoutComponent) MarginRight(x int) *LayoutComponent {
c.builder = c.builder.Raw(func(n *flex.Node) {
n.StyleSetMargin(flex.EdgeRight, float32(x))
})
return c
}
// PaddingLeft sets the `margin-left` property.
func (c *LayoutComponent) PaddingLeft(x int) *LayoutComponent {
c.builder = c.builder.Raw(func(n *flex.Node) {
n.StyleSetPadding(flex.EdgeLeft, float32(x))
})
return c
}
// PaddingRight sets the `margin-left` property.
func (c *LayoutComponent) PaddingRight(x int) *LayoutComponent {
c.builder = c.builder.Raw(func(n *flex.Node) {
n.StyleSetPadding(flex.EdgeRight, float32(x))
})
return c
}
// Component implementation
func (c *LayoutComponent) Body(context.Context) Component {
return Fragment(c.inner...)
}
// componentLayout internal implementation.
func (c *LayoutComponent) Layout() *layout.Builder {
return c.builder
}

199
vendor/github.com/mitchellh/go-glint/measure.go generated vendored Normal file
View File

@@ -0,0 +1,199 @@
package glint
import (
"context"
"math"
"strings"
"unicode/utf8"
"github.com/mitchellh/go-glint/flex"
"github.com/mitchellh/go-wordwrap"
)
// TextNodeContext is the *flex.Node.Context set for all *TextComponent flex nodes.
type TextNodeContext struct {
// C is the TextComponent represented.
C *TextComponent
// The context at the time layout was done
Context context.Context
// Text is the rendered text. This is populated after MeasureTextNode
// is called. Note that this may not fit in the final layout calculations
// since it is populated on measurement.
Text string
// Size is the measurement size returned. This can be used to determine
// if the text above fits in the final size. Text is guaranteed to fit
// in this size.
Size flex.Size
}
func (c *TextNodeContext) Component() Component { return c.C }
// MeasureTextNode implements flex.MeasureFunc and returns the measurements
// for the given node only if the node represents a TextComponent. This is
// the MeasureFunc that is typically used for renderers since all component
// trees terminate in a text node.
//
// The flex.Node must have Context set to TextNodeContext. After calling this,
// fields such as Text and Size will be populated on the node.
func MeasureTextNode(
node *flex.Node,
width float32,
widthMode flex.MeasureMode,
height float32,
heightMode flex.MeasureMode,
) flex.Size {
// If we have no context set then we use the full spacing.
ctx, ok := node.Context.(*TextNodeContext)
if !ok || ctx == nil {
return flex.Size{Width: width, Height: height}
}
// Otherwise, we have to render this.
ctx.Text = ctx.C.Render(uint(height), uint(width))
// Word wrap and truncate if we're beyond the width limit.
if !math.IsNaN(float64(width)) && width > 0 {
ctx.Text = clampTextWidth(
wordwrap.WrapString(ctx.Text, uint(width)),
int(width))
}
// Truncate height if we have a limit. This is a no-op if it fits.
if !math.IsNaN(float64(height)) && height > 0 {
ctx.Text = truncateTextHeight(ctx.Text, int(height))
}
// Calculate the size
ctx.Size = flex.Size{
Width: float32(longestLine(ctx.Text)),
Height: float32(countLines(ctx.Text)),
}
// We special case the empty-text case, since this is a height of
// one and width of zero. If the user wanted no rendering at all they
// should render nil.
if ctx.Text == "" {
ctx.Size.Height = 1
}
return ctx.Size
}
func countLines(s string) int {
count := strings.Count(s, "\n")
// If the last character isn't a newline, we have to add one since we'll
// always have one more line than newline characters.
if len(s) > 0 && s[len(s)-1] != '\n' {
count++
}
return count
}
func longestLine(s string) int {
longest := 0
for {
idx := strings.IndexByte(s, '\n')
if idx == -1 {
break
}
current := utf8.RuneCountInString(s[:idx])
if current > longest {
longest = current
}
s = s[idx+1:]
}
if longest == 0 {
return utf8.RuneCountInString(s)
}
return longest
}
func truncateTextHeight(s string, height int) string {
// The way this works is that we iterate through HEIGHT newlines
// and return up to that point. If we either don't find a newline
// or we've reached the end of the string, then the string is shorter
// than the height limit and we return the whole thing.
idx := 0
for i := 0; i < height; i++ {
next := strings.IndexByte(s[idx:], '\n')
if next == -1 || idx >= len(s) {
return s
}
idx += next + 1
}
// This can happen if height == 0
if idx == 0 {
return ""
}
// Subtract one here because the idx is the last "\n" char
return s[:idx-1]
}
// clampTextWidth cuts off any lines in s that are longer than width
// characters (not including the newline).
func clampTextWidth(s string, width int) string {
// If our width is zero just return empty
if width == 0 {
return ""
}
// NOTE(mitchellh): This loop is really horrible. It is unclear, weirdly
// repetitive, and just aesthetically gross. But the tests pass and we have
// good test cases on this. Let's fix this later.
var b *strings.Builder
total := 0
original := s
for {
end := false
idx := strings.IndexByte(s, '\n')
if idx == -1 {
idx = len(s)
end = true
}
runeCount := utf8.RuneCountInString(s[:idx])
if runeCount > width {
if b == nil {
b = &strings.Builder{}
if total > 0 {
b.WriteString(original[:total])
b.WriteByte('\n')
}
}
runes := []rune(s)
b.WriteString(string(runes[:width]))
if !end {
b.WriteByte('\n')
}
} else if idx > 0 {
if b != nil {
b.WriteString(s[:idx])
}
}
if end {
break
}
total += idx
s = s[idx+1:]
}
if b == nil {
return original
}
return b.String()
}

54
vendor/github.com/mitchellh/go-glint/renderer.go generated vendored Normal file
View File

@@ -0,0 +1,54 @@
package glint
import (
"context"
"github.com/mitchellh/go-glint/flex"
)
// Renderers are responsible for helping configure layout properties and
// ultimately drawing components.
//
// Renderers may also optionally implement io.Closer. If a renderer implements
// io.Closer, the Close method will be called. After this is called. the
// Render methods will no longer be called again. This can be used to perform
// final cleanups.
type Renderer interface {
// LayoutRoot returns the root node for the layout engine. This should
// set any styling to restrict children such as width. If this returns nil
// then rendering will do nothing.
LayoutRoot() *flex.Node
// RenderRoot is called to render the tree rooted at the given node.
// This will always be called with the root node. In the future we plan
// to support partial re-renders but this will be done via a separate call.
//
// The height of root is always greater than zero. RenderRoot won't be
// called if the root has a zero height since this implies that nothing
// has to be drawn.
//
// prev will be the previous root that was rendered. This can be used to
// determine layout differences. This will be nil if this is the first
// render. If the height of the previous node is zero then that means that
// everything drawn was finalized.
RenderRoot(root, prev *flex.Node)
}
// WithRenderer inserts the renderer into the context. This is done automatically
// by Document for components.
func WithRenderer(ctx context.Context, r Renderer) context.Context {
return context.WithValue(ctx, rendererCtxKey, r)
}
// RendererFromContext returns the Renderer in the context or nil if no
// Renderer is found.
func RendererFromContext(ctx context.Context) Renderer {
v, _ := ctx.Value(rendererCtxKey).(Renderer)
return v
}
type glintCtxKey string
const (
rendererCtxKey = glintCtxKey("renderer")
)

103
vendor/github.com/mitchellh/go-glint/renderer_string.go generated vendored Normal file
View File

@@ -0,0 +1,103 @@
package glint
import (
"bytes"
"fmt"
"io"
"strings"
"github.com/mitchellh/go-glint/flex"
)
// StringRenderer renders output to a string builder. This will clear
// the builder on each frame render. The StringRenderer is primarily meant
// for testing components.
type StringRenderer struct {
// Builder is the strings builder to write to. If this is nil then
// it will be created on first render.
Builder *strings.Builder
// Width is a fixed width to set for the root node. If this isn't
// set then a width of 80 is arbitrarily used.
Width uint
}
func (r *StringRenderer) LayoutRoot() *flex.Node {
width := r.Width
if width == 0 {
width = 80
}
node := flex.NewNode()
node.StyleSetWidth(float32(width))
return node
}
func (r *StringRenderer) RenderRoot(root, prev *flex.Node) {
if r.Builder == nil {
r.Builder = &strings.Builder{}
}
// Reset our builder
r.Builder.Reset()
// Draw
r.renderTree(r.Builder, root, -1, false)
}
func (r *StringRenderer) renderTree(final io.Writer, parent *flex.Node, lastRow int, color bool) {
var buf bytes.Buffer
for _, child := range parent.Children {
// Ignore children with a zero height
if child.LayoutGetHeight() == 0 {
continue
}
// If we're on a different row than last time then we draw a newline.
thisRow := int(child.LayoutGetTop())
if lastRow >= 0 && thisRow > lastRow {
buf.WriteByte('\n')
}
lastRow = thisRow
// Get our node context. If we don't have one then we're a container
// and we render below.
ctx, ok := child.Context.(*TextNodeContext)
if !ok {
r.renderTree(&buf, child, lastRow, color)
} else {
text := ctx.Text
if color {
text = styleRender(ctx.Context, text)
}
// Draw our text
fmt.Fprint(&buf, text)
}
}
// We've finished drawing our main content. If we have any paddings/margins
// we have to draw these now into our buffer.
leftMargin := int(parent.LayoutGetMargin(flex.EdgeLeft))
rightMargin := int(parent.LayoutGetMargin(flex.EdgeRight))
leftPadding := int(parent.LayoutGetPadding(flex.EdgeLeft))
rightPadding := int(parent.LayoutGetPadding(flex.EdgeRight))
// NOTE(mitchellh): this is not an optimal way to do this. This was a
// get-it-done-fast implementation. We should swing back around at some
// point and rewrite this with less allocations and copying.
lines := bytes.Split(buf.Bytes(), newline)
for i, line := range lines {
final.Write(bytes.Repeat(space, leftMargin+leftPadding))
final.Write(line)
final.Write(bytes.Repeat(space, rightMargin+rightPadding))
if i < len(lines)-1 {
final.Write(newline)
}
}
}
var (
space = []byte(" ")
newline = []byte("\n")
)

126
vendor/github.com/mitchellh/go-glint/renderer_term.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package glint
import (
"bytes"
"fmt"
"io"
"os"
"github.com/containerd/console"
"github.com/gookit/color"
"github.com/morikuni/aec"
sshterm "golang.org/x/crypto/ssh/terminal"
"github.com/mitchellh/go-glint/flex"
)
// TerminalRenderer renders output to a terminal. It expects the Output set
// to be a TTY. This will use ANSI escape codes to redraw.
type TerminalRenderer struct {
// Output is where to write to. This should be a TTY.
Output io.Writer
// Rows, Cols are the dimensions of the terminal. If these are not set
// (zero), then we will auto-detect the size of the output if it is a TTY.
// If the values are still zero, nothing will be rendered.
Rows, Cols uint
}
func (r *TerminalRenderer) LayoutRoot() *flex.Node {
// If we don't have a writer set, then don't render anything.
if r.Output == nil {
return nil
}
// Setup our dimensions
cols := r.Cols
rows := r.Rows
if cols == 0 || rows == 0 {
if f, ok := r.Output.(*os.File); ok && sshterm.IsTerminal(int(f.Fd())) {
if c, err := console.ConsoleFromFile(f); err == nil {
if sz, err := c.Size(); err == nil {
rows = uint(sz.Height)
cols = uint(sz.Width)
}
}
}
}
// Render nothing if we're going to have any zero dimensions
if cols == 0 || rows == 0 {
return nil
}
// Setup our node
node := flex.NewNode()
node.StyleSetWidth(float32(cols))
node.Context = &termRootContext{
Rows: rows,
Cols: cols,
}
return node
}
func (r *TerminalRenderer) RenderRoot(root, prev *flex.Node) {
w := r.Output
rootCtx := root.Context.(*termRootContext)
// Draw into a buffer first. This minimizes the time we spend with
// a blank screen.
var buf bytes.Buffer
var sr StringRenderer
sr.renderTree(&buf, root, -1, color.IsSupportColor())
rootCtx.Buf = &buf
if prev != nil {
// If the previous draw was a terminal and the output was identical,
// then we do nothing.
prevCtx, ok := prev.Context.(*termRootContext)
if ok &&
prevCtx != nil &&
prevCtx.Buf != nil &&
prevCtx.Rows == rootCtx.Rows &&
prevCtx.Cols == rootCtx.Cols &&
bytes.Equal(prevCtx.Buf.Bytes(), buf.Bytes()) {
return
}
// Remove what we last drew. If what we last drew is greater than the number
// of rows then we need to clear the screen.
height := uint(prev.LayoutGetHeight())
if height == 0 {
// If our previous render height is zero that means that everything
// was finalized and we need to start on a new line.
fmt.Fprintf(w, "\n")
} else {
if height <= rootCtx.Rows {
// Delete current line
fmt.Fprint(w, b.Column(0).EraseLine(aec.EraseModes.All).ANSI)
// Delete n lines above
for i := uint(0); i < height-1; i++ {
fmt.Fprint(w, b.Up(1).Column(0).EraseLine(aec.EraseModes.All).ANSI)
}
} else {
fmt.Fprint(w, b.EraseDisplay(aec.EraseModes.All).EraseDisplay(aec.EraseMode(3)).Position(0, 0).ANSI)
}
}
}
// Draw our current output. We wrap buf in a bytes.Reader so we don't
// consume the bytes since we'll reuse them in a future call.
io.Copy(w, bytes.NewReader(buf.Bytes()))
}
func (r *TerminalRenderer) Close() error {
fmt.Fprintln(r.Output, "")
return nil
}
type termRootContext struct {
Rows, Cols uint
Buf *bytes.Buffer
}
var b = aec.EmptyBuilder

152
vendor/github.com/mitchellh/go-glint/style.go generated vendored Normal file
View File

@@ -0,0 +1,152 @@
package glint
import (
"context"
"github.com/gookit/color"
)
// Style applies visual styles to this component and any children. This
// can be used to set a foreground color, for example, to a set of components.
func Style(inner Component, opts ...StyleOption) Component {
c := &styleComponent{inner: inner}
for _, opt := range opts {
opt(c)
}
return c
}
// styleRender is used internally to apply styles to the given string. The
// ctx should be the same context given when Body was called on this
// component.
func styleRender(ctx context.Context, v string) string {
value, _ := ctx.Value(styleCtxKey).([]*styleComponent)
for _, s := range value {
v = s.render(v)
}
return v
}
type styleComponent struct {
inner Component
fgColor, bgColor colorizer
style []color.Color
}
func (c *styleComponent) Body(ctx context.Context) Component {
// Add our style to the list of styles. We have to use copy here
// so we don't append to a parent.
old, _ := ctx.Value(styleCtxKey).([]*styleComponent)
value := make([]*styleComponent, len(old), len(old)+1)
copy(value, old)
value = append(value, c)
return Context(c.inner, styleCtxKey, value)
}
func (c *styleComponent) render(v string) string {
if c.bgColor != nil {
v = c.bgColor.Sprint(v)
}
if c.fgColor != nil {
v = c.fgColor.Sprint(v)
}
v = color.Style(c.style).Sprint(v)
return v
}
type styleCtxKeyType struct{}
var styleCtxKey = styleCtxKeyType{}
// StyleOption is an option that can be set when creating Text components.
type StyleOption func(t *styleComponent)
// Color sets the color by name. The supported colors are listed below.
//
// black, red, green, yellow, blue, magenta, cyan, white, darkGray,
// lightRed, lightGreen, lightYellow, lightBlue, lightMagenta, lightCyan,
// lightWhite.
func Color(name string) StyleOption {
return func(t *styleComponent) {
if c, ok := color.FgColors[name]; ok {
t.fgColor = c
}
if c, ok := color.ExFgColors[name]; ok {
t.fgColor = c
}
}
}
// ColorHex sets the foreground color by hex code. The value can be
// in formats AABBCC, #AABBCC, 0xAABBCC.
func ColorHex(v string) StyleOption {
return func(t *styleComponent) {
t.fgColor = color.HEX(v)
}
}
// ColorRGB sets the foreground color by RGB values.
func ColorRGB(r, g, b uint8) StyleOption {
return func(t *styleComponent) {
t.fgColor = color.RGB(r, g, b)
}
}
// BGColor sets the color by name. The supported colors are listed below.
//
// black, red, green, yellow, blue, magenta, cyan, white, darkGray,
// lightRed, lightGreen, lightYellow, lightBlue, lightMagenta, lightCyan,
// lightWhite.
func BGColor(name string) StyleOption {
return func(t *styleComponent) {
if c, ok := color.BgColors[name]; ok {
t.bgColor = c
}
if c, ok := color.ExBgColors[name]; ok {
t.bgColor = c
}
}
}
// BGColorHex sets the foreground color by hex code. The value can be
// in formats AABBCC, #AABBCC, 0xAABBCC.
func BGColorHex(v string) StyleOption {
return func(t *styleComponent) {
t.bgColor = color.HEX(v, true)
}
}
// BGColorRGB sets the foreground color by RGB values.
func BGColorRGB(r, g, b uint8) StyleOption {
return func(t *styleComponent) {
t.bgColor = color.RGB(r, g, b, true)
}
}
// Bold sets the text to bold.
func Bold() StyleOption {
return func(t *styleComponent) {
t.style = append(t.style, color.OpBold)
}
}
// Italic sets the text to italic.
func Italic() StyleOption {
return func(t *styleComponent) {
t.style = append(t.style, color.OpItalic)
}
}
// Underline sets the text to be underlined.
func Underline() StyleOption {
return func(t *styleComponent) {
t.style = append(t.style, color.OpUnderscore)
}
}
type colorizer interface {
Sprint(...interface{}) string
}

19
vendor/github.com/mitchellh/go-glint/testing.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package glint
import (
"github.com/mitchellh/go-testing-interface"
)
// TestRender renders the component using the string renderer and returns
// the string. This is a test helper function for writing components.
func TestRender(t testing.T, c Component) string {
// Note that nothing here fails at the moment so the t param above is
// unneeded but we're gonna keep it around in case we need it in the future
// so we don't have to break API.
r := &StringRenderer{}
d := New()
d.SetRenderer(r)
d.Append(c)
d.RenderFrame()
return r.Builder.String()
}

37
vendor/github.com/mitchellh/go-glint/text.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package glint
import (
"context"
)
// TextComponent is a Component that renders text.
type TextComponent struct {
terminalComponent
f func(rows, cols uint) string
}
// Text creates a TextComponent for static text. The text here will be word
// wrapped automatically based on the width of the terminal.
func Text(v string) *TextComponent {
return TextFunc(func(rows, cols uint) string { return v })
}
// TextFunc creates a TextComponent for text that is dependent on the
// size of the draw area.
func TextFunc(f func(rows, cols uint) string) *TextComponent {
return &TextComponent{
f: f,
}
}
func (el *TextComponent) Body(context.Context) Component {
return nil
}
func (el *TextComponent) Render(rows, cols uint) string {
if el.f == nil {
return ""
}
return el.f(rows, cols)
}

87
vendor/github.com/mitchellh/go-glint/tree.go generated vendored Normal file
View File

@@ -0,0 +1,87 @@
package glint
import (
"context"
"github.com/mitchellh/go-glint/flex"
)
func tree(
ctx context.Context,
parent *flex.Node,
c Component,
finalize bool,
) {
// Don't do anything with no component
if c == nil {
return
}
// Fragments don't create a node
switch c := c.(type) {
case *contextComponent:
for i := 0; i < len(c.pairs); i += 2 {
ctx = context.WithValue(ctx, c.pairs[i], c.pairs[i+1])
}
tree(ctx, parent, c.inner, finalize)
return
case *fragmentComponent:
for _, c := range c.List {
tree(ctx, parent, c, finalize)
}
return
}
// Setup our node
node := flex.NewNodeWithConfig(parent.Config)
parent.InsertChild(node, len(parent.Children))
// Setup our default context
parentCtx := &parentContext{C: c}
node.Context = parentCtx
// Check if we're finalized and note it
if _, ok := c.(*finalizedComponent); ok {
parentCtx.Finalized = true
}
// Finalize
if finalize {
if c, ok := c.(ComponentFinalizer); ok {
c.Finalize()
}
}
// Setup a custom layout
if c, ok := c.(componentLayout); ok {
c.Layout().Apply(node)
}
switch c := c.(type) {
case *TextComponent:
node.Context = &TextNodeContext{C: c, Context: ctx}
node.StyleSetFlexShrink(1)
node.StyleSetFlexGrow(0)
node.StyleSetFlexDirection(flex.FlexDirectionRow)
node.SetMeasureFunc(MeasureTextNode)
default:
// If this is not terminal then we nest.
tree(ctx, node, c.Body(ctx), finalize)
}
}
type parentContext struct {
C Component
Finalized bool
}
func (c *parentContext) Component() Component { return c.C }
type treeContext interface {
Component() Component
}

View File

@@ -1,7 +1,6 @@
language: go
go:
- 1.8
- 1.x
- tip

View File

@@ -38,6 +38,14 @@ You can also call the test helper at runtime if needed:
TestHelper(&testing.RuntimeT{})
}
## Versioning
The tagged version matches the version of Go that the interface is
compatible with. For example, the version "1.14.0" is for Go 1.14 and
introduced the `Cleanup` function. The patch version (the ".0" in the
prior example) is used to fix any bugs found in this library and has no
correlation to the supported Go version.
## Why?!
**Why would I call a test helper that takes a *testing.T at runtime?**

View File

@@ -1 +1,3 @@
module github.com/mitchellh/go-testing-interface
go 1.14

View File

@@ -1,5 +1,3 @@
// +build !go1.9
package testing
import (
@@ -12,6 +10,7 @@ import (
// In unit tests you can just pass a *testing.T struct. At runtime, outside
// of tests, you can pass in a RuntimeT struct from this package.
type T interface {
Cleanup(func())
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fail()
@@ -19,6 +18,7 @@ type T interface {
Failed() bool
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Helper()
Log(args ...interface{})
Logf(format string, args ...interface{})
Name() string
@@ -34,10 +34,13 @@ type T interface {
// for calls to Fatal. For calls to Error, you'll have to check the errors
// list to determine whether to exit yourself.
//
// Cleanup does NOT work, so if you're using a helper that uses Cleanup,
// there may be dangling resources.
//
// Parallel does not do anything.
type RuntimeT struct {
failed bool
skipped bool
failed bool
}
func (t *RuntimeT) Error(args ...interface{}) {
@@ -46,20 +49,10 @@ func (t *RuntimeT) Error(args ...interface{}) {
}
func (t *RuntimeT) Errorf(format string, args ...interface{}) {
log.Println(fmt.Sprintf(format, args...))
log.Printf(format, args...)
t.Fail()
}
func (t *RuntimeT) Fatal(args ...interface{}) {
log.Println(fmt.Sprintln(args...))
t.FailNow()
}
func (t *RuntimeT) Fatalf(format string, args ...interface{}) {
log.Println(fmt.Sprintf(format, args...))
t.FailNow()
}
func (t *RuntimeT) Fail() {
t.failed = true
}
@@ -72,6 +65,16 @@ func (t *RuntimeT) Failed() bool {
return t.failed
}
func (t *RuntimeT) Fatal(args ...interface{}) {
log.Print(args...)
t.FailNow()
}
func (t *RuntimeT) Fatalf(format string, args ...interface{}) {
log.Printf(format, args...)
t.FailNow()
}
func (t *RuntimeT) Log(args ...interface{}) {
log.Println(fmt.Sprintln(args...))
}
@@ -103,3 +106,7 @@ func (t *RuntimeT) Skipf(format string, args ...interface{}) {
func (t *RuntimeT) Skipped() bool {
return t.skipped
}
func (t *RuntimeT) Helper() {}
func (t *RuntimeT) Cleanup(func()) {}

View File

@@ -1,108 +0,0 @@
// +build go1.9
// NOTE: This is a temporary copy of testing.go for Go 1.9 with the addition
// of "Helper" to the T interface. Go 1.9 at the time of typing is in RC
// and is set for release shortly. We'll support this on master as the default
// as soon as 1.9 is released.
package testing
import (
"fmt"
"log"
)
// T is the interface that mimics the standard library *testing.T.
//
// In unit tests you can just pass a *testing.T struct. At runtime, outside
// of tests, you can pass in a RuntimeT struct from this package.
type T interface {
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fail()
FailNow()
Failed() bool
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Log(args ...interface{})
Logf(format string, args ...interface{})
Name() string
Skip(args ...interface{})
SkipNow()
Skipf(format string, args ...interface{})
Skipped() bool
Helper()
}
// RuntimeT implements T and can be instantiated and run at runtime to
// mimic *testing.T behavior. Unlike *testing.T, this will simply panic
// for calls to Fatal. For calls to Error, you'll have to check the errors
// list to determine whether to exit yourself.
type RuntimeT struct {
skipped bool
failed bool
}
func (t *RuntimeT) Error(args ...interface{}) {
log.Println(fmt.Sprintln(args...))
t.Fail()
}
func (t *RuntimeT) Errorf(format string, args ...interface{}) {
log.Printf(format, args...)
t.Fail()
}
func (t *RuntimeT) Fail() {
t.failed = true
}
func (t *RuntimeT) FailNow() {
panic("testing.T failed, see logs for output (if any)")
}
func (t *RuntimeT) Failed() bool {
return t.failed
}
func (t *RuntimeT) Fatal(args ...interface{}) {
log.Print(args...)
t.FailNow()
}
func (t *RuntimeT) Fatalf(format string, args ...interface{}) {
log.Printf(format, args...)
t.FailNow()
}
func (t *RuntimeT) Log(args ...interface{}) {
log.Println(fmt.Sprintln(args...))
}
func (t *RuntimeT) Logf(format string, args ...interface{}) {
log.Println(fmt.Sprintf(format, args...))
}
func (t *RuntimeT) Name() string {
return ""
}
func (t *RuntimeT) Skip(args ...interface{}) {
log.Print(args...)
t.SkipNow()
}
func (t *RuntimeT) SkipNow() {
t.skipped = true
}
func (t *RuntimeT) Skipf(format string, args ...interface{}) {
log.Printf(format, args...)
t.SkipNow()
}
func (t *RuntimeT) Skipped() bool {
return t.skipped
}
func (t *RuntimeT) Helper() {}

View File

@@ -1 +1,3 @@
module github.com/mitchellh/go-wordwrap
go 1.14

View File

@@ -5,6 +5,8 @@ import (
"unicode"
)
const nbsp = 0xA0
// WrapString wraps the given string within lim width in characters.
//
// Wrapping is currently naive and only happens at white-space. A future
@@ -18,50 +20,58 @@ func WrapString(s string, lim uint) string {
var current uint
var wordBuf, spaceBuf bytes.Buffer
var wordBufLen, spaceBufLen uint
for _, char := range s {
if char == '\n' {
if wordBuf.Len() == 0 {
if current+uint(spaceBuf.Len()) > lim {
if current+spaceBufLen > lim {
current = 0
} else {
current += uint(spaceBuf.Len())
current += spaceBufLen
spaceBuf.WriteTo(buf)
}
spaceBuf.Reset()
spaceBufLen = 0
} else {
current += uint(spaceBuf.Len() + wordBuf.Len())
current += spaceBufLen + wordBufLen
spaceBuf.WriteTo(buf)
spaceBuf.Reset()
spaceBufLen = 0
wordBuf.WriteTo(buf)
wordBuf.Reset()
wordBufLen = 0
}
buf.WriteRune(char)
current = 0
} else if unicode.IsSpace(char) {
} else if unicode.IsSpace(char) && char != nbsp {
if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
current += uint(spaceBuf.Len() + wordBuf.Len())
current += spaceBufLen + wordBufLen
spaceBuf.WriteTo(buf)
spaceBuf.Reset()
spaceBufLen = 0
wordBuf.WriteTo(buf)
wordBuf.Reset()
wordBufLen = 0
}
spaceBuf.WriteRune(char)
spaceBufLen++
} else {
wordBuf.WriteRune(char)
wordBufLen++
if current+uint(spaceBuf.Len()+wordBuf.Len()) > lim && uint(wordBuf.Len()) < lim {
if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim {
buf.WriteRune('\n')
current = 0
spaceBuf.Reset()
spaceBufLen = 0
}
}
}
if wordBuf.Len() == 0 {
if current+uint(spaceBuf.Len()) <= lim {
if current+spaceBufLen <= lim {
spaceBuf.WriteTo(buf)
}
} else {

Some files were not shown because too many files have changed in this diff Show More