mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 18:35:44 +03:00
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:
committed by
Isabel Suchanek
parent
66d590c64b
commit
0edda116ad
2
vendor/github.com/VividCortex/ewma/.gitignore
generated
vendored
Normal file
2
vendor/github.com/VividCortex/ewma/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
.*.sw?
|
||||
21
vendor/github.com/VividCortex/ewma/LICENSE
generated
vendored
Normal file
21
vendor/github.com/VividCortex/ewma/LICENSE
generated
vendored
Normal 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
140
vendor/github.com/VividCortex/ewma/README.md
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
# EWMA [](https://godoc.org/github.com/VividCortex/ewma) 
|
||||
|
||||
This repo provides Exponentially Weighted Moving Average algorithms, or EWMAs for short, [based on our
|
||||
Quantifying Abnormal Behavior talk](https://vividcortex.com/blog/2013/07/23/a-fast-go-library-for-exponential-moving-averages/).
|
||||
|
||||
### Exponentially Weighted Moving Average
|
||||
|
||||
An exponentially weighted moving average is a way to continuously compute a type of
|
||||
average for a series of numbers, as the numbers arrive. After a value in the series is
|
||||
added to the average, its weight in the average decreases exponentially over time. This
|
||||
biases the average towards more recent data. EWMAs are useful for several reasons, chiefly
|
||||
their inexpensive computational and memory cost, as well as the fact that they represent
|
||||
the recent central tendency of the series of values.
|
||||
|
||||
The EWMA algorithm requires a decay factor, alpha. The larger the alpha, the more the average
|
||||
is biased towards recent history. The alpha must be between 0 and 1, and is typically
|
||||
a fairly small number, such as 0.04. We will discuss the choice of alpha later.
|
||||
|
||||
The algorithm works thus, in pseudocode:
|
||||
|
||||
1. Multiply the next number in the series by alpha.
|
||||
2. Multiply the current value of the average by 1 minus alpha.
|
||||
3. Add the result of steps 1 and 2, and store it as the new current value of the average.
|
||||
4. Repeat for each number in the series.
|
||||
|
||||
There are special-case behaviors for how to initialize the current value, and these vary
|
||||
between implementations. One approach is to start with the first value in the series;
|
||||
another is to average the first 10 or so values in the series using an arithmetic average,
|
||||
and then begin the incremental updating of the average. Each method has pros and cons.
|
||||
|
||||
It may help to look at it pictorially. Suppose the series has five numbers, and we choose
|
||||
alpha to be 0.50 for simplicity. Here's the series, with numbers in the neighborhood of 300.
|
||||
|
||||

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

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

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

|
||||
|
||||
Notice how each of the values in the series decays by half each time a new value
|
||||
is added, and the top of the bars in the lower portion of the image represents the
|
||||
size of the moving average. It is a smoothed, or low-pass, average of the original
|
||||
series.
|
||||
|
||||
For further reading, see [Exponentially weighted moving average](http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) on wikipedia.
|
||||
|
||||
### Choosing Alpha
|
||||
|
||||
Consider a fixed-size sliding-window moving average (not an exponentially weighted moving average)
|
||||
that averages over the previous N samples. What is the average age of each sample? It is N/2.
|
||||
|
||||
Now suppose that you wish to construct a EWMA whose samples have the same average age. The formula
|
||||
to compute the alpha required for this is: alpha = 2/(N+1). Proof is in the book
|
||||
"Production and Operations Analysis" by Steven Nahmias.
|
||||
|
||||
So, for example, if you have a time-series with samples once per second, and you want to get the
|
||||
moving average over the previous minute, you should use an alpha of .032786885. This, by the way,
|
||||
is the constant alpha used for this repository's SimpleEWMA.
|
||||
|
||||
### Implementations
|
||||
|
||||
This repository contains two implementations of the EWMA algorithm, with different properties.
|
||||
|
||||
The implementations all conform to the MovingAverage interface, and the constructor returns
|
||||
that type.
|
||||
|
||||
Current implementations assume an implicit time interval of 1.0 between every sample added.
|
||||
That is, the passage of time is treated as though it's the same as the arrival of samples.
|
||||
If you need time-based decay when samples are not arriving precisely at set intervals, then
|
||||
this package will not support your needs at present.
|
||||
|
||||
#### SimpleEWMA
|
||||
|
||||
A SimpleEWMA is designed for low CPU and memory consumption. It **will** have different behavior than the VariableEWMA
|
||||
for multiple reasons. It has no warm-up period and it uses a constant
|
||||
decay. These properties let it use less memory. It will also behave
|
||||
differently when it's equal to zero, which is assumed to mean
|
||||
uninitialized, so if a value is likely to actually become zero over time,
|
||||
then any non-zero value will cause a sharp jump instead of a small change.
|
||||
|
||||
#### VariableEWMA
|
||||
|
||||
Unlike SimpleEWMA, this supports a custom age which must be stored, and thus uses more memory.
|
||||
It also has a "warmup" time when you start adding values to it. It will report a value of 0.0
|
||||
until you have added the required number of samples to it. It uses some memory to store the
|
||||
number of samples added to it. As a result it uses a little over twice the memory of SimpleEWMA.
|
||||
|
||||
## Usage
|
||||
|
||||
### API Documentation
|
||||
|
||||
View the GoDoc generated documentation [here](http://godoc.org/github.com/VividCortex/ewma).
|
||||
|
||||
```go
|
||||
package main
|
||||
import "github.com/VividCortex/ewma"
|
||||
|
||||
func main() {
|
||||
samples := [100]float64{
|
||||
4599, 5711, 4746, 4621, 5037, 4218, 4925, 4281, 5207, 5203, 5594, 5149,
|
||||
}
|
||||
|
||||
e := ewma.NewMovingAverage() //=> Returns a SimpleEWMA if called without params
|
||||
a := ewma.NewMovingAverage(5) //=> returns a VariableEWMA with a decay of 2 / (5 + 1)
|
||||
|
||||
for _, f := range samples {
|
||||
e.Add(f)
|
||||
a.Add(f)
|
||||
}
|
||||
|
||||
e.Value() //=> 13.577404704631077
|
||||
a.Value() //=> 1.5806140565521463e-12
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We only accept pull requests for minor fixes or improvements. This includes:
|
||||
|
||||
* Small bug fixes
|
||||
* Typos
|
||||
* Documentation or comments
|
||||
|
||||
Please open issues to discuss new features. Pull requests for new features will be rejected,
|
||||
so we recommend forking the repository and making changes in your fork for your use case.
|
||||
|
||||
## License
|
||||
|
||||
This repository is Copyright (c) 2013 VividCortex, Inc. All rights reserved.
|
||||
It is licensed under the MIT license. Please see the LICENSE file for applicable license terms.
|
||||
126
vendor/github.com/VividCortex/ewma/ewma.go
generated
vendored
Normal file
126
vendor/github.com/VividCortex/ewma/ewma.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Package ewma implements exponentially weighted moving averages.
|
||||
package ewma
|
||||
|
||||
// Copyright (c) 2013 VividCortex, Inc. All rights reserved.
|
||||
// Please see the LICENSE file for applicable license terms.
|
||||
|
||||
const (
|
||||
// By default, we average over a one-minute period, which means the average
|
||||
// age of the metrics in the period is 30 seconds.
|
||||
AVG_METRIC_AGE float64 = 30.0
|
||||
|
||||
// The formula for computing the decay factor from the average age comes
|
||||
// from "Production and Operations Analysis" by Steven Nahmias.
|
||||
DECAY float64 = 2 / (float64(AVG_METRIC_AGE) + 1)
|
||||
|
||||
// For best results, the moving average should not be initialized to the
|
||||
// samples it sees immediately. The book "Production and Operations
|
||||
// Analysis" by Steven Nahmias suggests initializing the moving average to
|
||||
// the mean of the first 10 samples. Until the VariableEwma has seen this
|
||||
// many samples, it is not "ready" to be queried for the value of the
|
||||
// moving average. This adds some memory cost.
|
||||
WARMUP_SAMPLES uint8 = 10
|
||||
)
|
||||
|
||||
// MovingAverage is the interface that computes a moving average over a time-
|
||||
// series stream of numbers. The average may be over a window or exponentially
|
||||
// decaying.
|
||||
type MovingAverage interface {
|
||||
Add(float64)
|
||||
Value() float64
|
||||
Set(float64)
|
||||
}
|
||||
|
||||
// NewMovingAverage constructs a MovingAverage that computes an average with the
|
||||
// desired characteristics in the moving window or exponential decay. If no
|
||||
// age is given, it constructs a default exponentially weighted implementation
|
||||
// that consumes minimal memory. The age is related to the decay factor alpha
|
||||
// by the formula given for the DECAY constant. It signifies the average age
|
||||
// of the samples as time goes to infinity.
|
||||
func NewMovingAverage(age ...float64) MovingAverage {
|
||||
if len(age) == 0 || age[0] == AVG_METRIC_AGE {
|
||||
return new(SimpleEWMA)
|
||||
}
|
||||
return &VariableEWMA{
|
||||
decay: 2 / (age[0] + 1),
|
||||
}
|
||||
}
|
||||
|
||||
// A SimpleEWMA represents the exponentially weighted moving average of a
|
||||
// series of numbers. It WILL have different behavior than the VariableEWMA
|
||||
// for multiple reasons. It has no warm-up period and it uses a constant
|
||||
// decay. These properties let it use less memory. It will also behave
|
||||
// differently when it's equal to zero, which is assumed to mean
|
||||
// uninitialized, so if a value is likely to actually become zero over time,
|
||||
// then any non-zero value will cause a sharp jump instead of a small change.
|
||||
// However, note that this takes a long time, and the value may just
|
||||
// decays to a stable value that's close to zero, but which won't be mistaken
|
||||
// for uninitialized. See http://play.golang.org/p/litxBDr_RC for example.
|
||||
type SimpleEWMA struct {
|
||||
// The current value of the average. After adding with Add(), this is
|
||||
// updated to reflect the average of all values seen thus far.
|
||||
value float64
|
||||
}
|
||||
|
||||
// Add adds a value to the series and updates the moving average.
|
||||
func (e *SimpleEWMA) Add(value float64) {
|
||||
if e.value == 0 { // this is a proxy for "uninitialized"
|
||||
e.value = value
|
||||
} else {
|
||||
e.value = (value * DECAY) + (e.value * (1 - DECAY))
|
||||
}
|
||||
}
|
||||
|
||||
// Value returns the current value of the moving average.
|
||||
func (e *SimpleEWMA) Value() float64 {
|
||||
return e.value
|
||||
}
|
||||
|
||||
// Set sets the EWMA's value.
|
||||
func (e *SimpleEWMA) Set(value float64) {
|
||||
e.value = value
|
||||
}
|
||||
|
||||
// VariableEWMA represents the exponentially weighted moving average of a series of
|
||||
// numbers. Unlike SimpleEWMA, it supports a custom age, and thus uses more memory.
|
||||
type VariableEWMA struct {
|
||||
// The multiplier factor by which the previous samples decay.
|
||||
decay float64
|
||||
// The current value of the average.
|
||||
value float64
|
||||
// The number of samples added to this instance.
|
||||
count uint8
|
||||
}
|
||||
|
||||
// Add adds a value to the series and updates the moving average.
|
||||
func (e *VariableEWMA) Add(value float64) {
|
||||
switch {
|
||||
case e.count < WARMUP_SAMPLES:
|
||||
e.count++
|
||||
e.value += value
|
||||
case e.count == WARMUP_SAMPLES:
|
||||
e.count++
|
||||
e.value = e.value / float64(WARMUP_SAMPLES)
|
||||
e.value = (value * e.decay) + (e.value * (1 - e.decay))
|
||||
default:
|
||||
e.value = (value * e.decay) + (e.value * (1 - e.decay))
|
||||
}
|
||||
}
|
||||
|
||||
// Value returns the current value of the average, or 0.0 if the series hasn't
|
||||
// warmed up yet.
|
||||
func (e *VariableEWMA) Value() float64 {
|
||||
if e.count <= WARMUP_SAMPLES {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return e.value
|
||||
}
|
||||
|
||||
// Set sets the EWMA's value.
|
||||
func (e *VariableEWMA) Set(value float64) {
|
||||
e.value = value
|
||||
if e.count <= WARMUP_SAMPLES {
|
||||
e.count = WARMUP_SAMPLES + 1
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/cheggaaa/pb/v3/LICENSE
generated
vendored
Normal file
12
vendor/github.com/cheggaaa/pb/v3/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (c) 2012-2015, Sergey Cherepanov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
290
vendor/github.com/cheggaaa/pb/v3/element.go
generated
vendored
Normal file
290
vendor/github.com/cheggaaa/pb/v3/element.go
generated
vendored
Normal 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
11
vendor/github.com/cheggaaa/pb/v3/go.mod
generated
vendored
Normal 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
21
vendor/github.com/cheggaaa/pb/v3/go.sum
generated
vendored
Normal 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
49
vendor/github.com/cheggaaa/pb/v3/io.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Reader it's a wrapper for given reader, but with progress handle
|
||||
type Reader struct {
|
||||
io.Reader
|
||||
bar *ProgressBar
|
||||
}
|
||||
|
||||
// Read reads bytes from wrapped reader and add amount of bytes to progress bar
|
||||
func (r *Reader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.Reader.Read(p)
|
||||
r.bar.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Close the wrapped reader when it implements io.Closer
|
||||
func (r *Reader) Close() (err error) {
|
||||
r.bar.Finish()
|
||||
if closer, ok := r.Reader.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Writer it's a wrapper for given writer, but with progress handle
|
||||
type Writer struct {
|
||||
io.Writer
|
||||
bar *ProgressBar
|
||||
}
|
||||
|
||||
// Write writes bytes to wrapped writer and add amount of bytes to progress bar
|
||||
func (r *Writer) Write(p []byte) (n int, err error) {
|
||||
n, err = r.Writer.Write(p)
|
||||
r.bar.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Close the wrapped reader when it implements io.Closer
|
||||
func (r *Writer) Close() (err error) {
|
||||
r.bar.Finish()
|
||||
if closer, ok := r.Writer.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
566
vendor/github.com/cheggaaa/pb/v3/pb.go
generated
vendored
Normal file
566
vendor/github.com/cheggaaa/pb/v3/pb.go
generated
vendored
Normal 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
15
vendor/github.com/cheggaaa/pb/v3/preset.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package pb
|
||||
|
||||
var (
|
||||
// Full - preset with all default available elements
|
||||
// Example: 'Prefix 20/100 [-->______] 20% 1 p/s ETA 1m Suffix'
|
||||
Full ProgressBarTemplate = `{{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
83
vendor/github.com/cheggaaa/pb/v3/speed.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/VividCortex/ewma"
|
||||
)
|
||||
|
||||
var speedAddLimit = time.Second / 2
|
||||
|
||||
type speed struct {
|
||||
ewma ewma.MovingAverage
|
||||
lastStateId uint64
|
||||
prevValue, startValue int64
|
||||
prevTime, startTime time.Time
|
||||
}
|
||||
|
||||
func (s *speed) value(state *State) float64 {
|
||||
if s.ewma == nil {
|
||||
s.ewma = ewma.NewMovingAverage()
|
||||
}
|
||||
if state.IsFirst() || state.Id() < s.lastStateId {
|
||||
s.reset(state)
|
||||
return 0
|
||||
}
|
||||
if state.Id() == s.lastStateId {
|
||||
return s.ewma.Value()
|
||||
}
|
||||
if state.IsFinished() {
|
||||
return s.absValue(state)
|
||||
}
|
||||
dur := state.Time().Sub(s.prevTime)
|
||||
if dur < speedAddLimit {
|
||||
return s.ewma.Value()
|
||||
}
|
||||
diff := math.Abs(float64(state.Value() - s.prevValue))
|
||||
lastSpeed := diff / dur.Seconds()
|
||||
s.prevTime = state.Time()
|
||||
s.prevValue = state.Value()
|
||||
s.lastStateId = state.Id()
|
||||
s.ewma.Add(lastSpeed)
|
||||
return s.ewma.Value()
|
||||
}
|
||||
|
||||
func (s *speed) reset(state *State) {
|
||||
s.lastStateId = state.Id()
|
||||
s.startTime = state.Time()
|
||||
s.prevTime = state.Time()
|
||||
s.startValue = state.Value()
|
||||
s.prevValue = state.Value()
|
||||
s.ewma = ewma.NewMovingAverage()
|
||||
}
|
||||
|
||||
func (s *speed) absValue(state *State) float64 {
|
||||
if dur := state.Time().Sub(s.startTime); dur > 0 {
|
||||
return float64(state.Value()) / dur.Seconds()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getSpeedObj(state *State) (s *speed) {
|
||||
if sObj, ok := state.Get(speedObj).(*speed); ok {
|
||||
return sObj
|
||||
}
|
||||
s = new(speed)
|
||||
state.Set(speedObj, s)
|
||||
return
|
||||
}
|
||||
|
||||
// ElementSpeed calculates current speed by EWMA
|
||||
// Optionally can take one or two string arguments.
|
||||
// First string will be used as value for format speed, default is "%s p/s".
|
||||
// Second string will be used when speed not available, default is "? p/s"
|
||||
// In template use as follows: {{speed .}} or {{speed . "%s per second"}} or {{speed . "%s ps" "..."}
|
||||
var ElementSpeed ElementFunc = func(state *State, args ...string) string {
|
||||
sp := getSpeedObj(state).value(state)
|
||||
if sp == 0 {
|
||||
return argsHelper(args).getNotEmptyOr(1, "? p/s")
|
||||
}
|
||||
return fmt.Sprintf(argsHelper(args).getNotEmptyOr(0, "%s p/s"), state.Format(int64(round(sp))))
|
||||
}
|
||||
88
vendor/github.com/cheggaaa/pb/v3/template.go
generated
vendored
Normal file
88
vendor/github.com/cheggaaa/pb/v3/template.go
generated
vendored
Normal 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
56
vendor/github.com/cheggaaa/pb/v3/termutil/term.go
generated
vendored
Normal 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()
|
||||
}
|
||||
}
|
||||
11
vendor/github.com/cheggaaa/pb/v3/termutil/term_appengine.go
generated
vendored
Normal file
11
vendor/github.com/cheggaaa/pb/v3/termutil/term_appengine.go
generated
vendored
Normal 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")
|
||||
}
|
||||
9
vendor/github.com/cheggaaa/pb/v3/termutil/term_bsd.go
generated
vendored
Normal file
9
vendor/github.com/cheggaaa/pb/v3/termutil/term_bsd.go
generated
vendored
Normal 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
|
||||
7
vendor/github.com/cheggaaa/pb/v3/termutil/term_linux.go
generated
vendored
Normal file
7
vendor/github.com/cheggaaa/pb/v3/termutil/term_linux.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build linux
|
||||
// +build !appengine
|
||||
|
||||
package termutil
|
||||
|
||||
const ioctlReadTermios = 0x5401 // syscall.TCGETS
|
||||
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
|
||||
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_nix.go
generated
vendored
Normal file
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_nix.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// +build linux darwin freebsd netbsd openbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package termutil
|
||||
|
||||
import "syscall"
|
||||
|
||||
const sysIoctl = syscall.SYS_IOCTL
|
||||
50
vendor/github.com/cheggaaa/pb/v3/termutil/term_plan9.go
generated
vendored
Normal file
50
vendor/github.com/cheggaaa/pb/v3/termutil/term_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package termutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
consctl *os.File
|
||||
|
||||
// Plan 9 doesn't have syscall.SIGQUIT
|
||||
unlockSignals = []os.Signal{
|
||||
os.Interrupt, syscall.SIGTERM, syscall.SIGKILL,
|
||||
}
|
||||
)
|
||||
|
||||
// TerminalWidth returns width of the terminal.
|
||||
func TerminalWidth() (int, error) {
|
||||
return 0, errors.New("Not supported")
|
||||
}
|
||||
|
||||
func lockEcho() error {
|
||||
if consctl != nil {
|
||||
return errors.New("consctl already open")
|
||||
}
|
||||
var err error
|
||||
consctl, err = os.OpenFile("/dev/consctl", os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = consctl.WriteString("rawon")
|
||||
if err != nil {
|
||||
consctl.Close()
|
||||
consctl = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockEcho() error {
|
||||
if consctl == nil {
|
||||
return nil
|
||||
}
|
||||
if err := consctl.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
consctl = nil
|
||||
return nil
|
||||
}
|
||||
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_solaris.go
generated
vendored
Normal file
8
vendor/github.com/cheggaaa/pb/v3/termutil/term_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// +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
155
vendor/github.com/cheggaaa/pb/v3/termutil/term_win.go
generated
vendored
Normal 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
76
vendor/github.com/cheggaaa/pb/v3/termutil/term_x.go
generated
vendored
Normal 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
115
vendor/github.com/cheggaaa/pb/v3/util.go
generated
vendored
Normal 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
20
vendor/github.com/gookit/color/.gitignore
generated
vendored
Normal 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
21
vendor/github.com/gookit/color/.travis.yml
generated
vendored
Normal 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
20
vendor/github.com/gookit/color/LICENSE
generated
vendored
Normal 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
422
vendor/github.com/gookit/color/README.md
generated
vendored
Normal file
@@ -0,0 +1,422 @@
|
||||
# CLI Color
|
||||
|
||||

|
||||
[](https://github.com/gookit/color/actions)
|
||||
[](https://app.codacy.com/app/inhere/color)
|
||||
[](https://pkg.go.dev/github.com/gookit/color?tab=overview)
|
||||
[](https://github.com/gookit/color)
|
||||
[](https://travis-ci.org/gookit/color)
|
||||
[](https://coveralls.io/github/gookit/color?branch=master)
|
||||
[](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:
|
||||
|
||||

|
||||
|
||||
Now, 256 colors and RGB colors have also been supported to work in Windows CMD and PowerShell:
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
### 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`
|
||||
|
||||

|
||||
|
||||
### 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`
|
||||
|
||||

|
||||
|
||||
### 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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
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
392
vendor/github.com/gookit/color/README.zh-CN.md
generated
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
# CLI Color
|
||||
|
||||

|
||||
[](https://github.com/gookit/color/actions)
|
||||
[](https://app.codacy.com/app/inhere/color)
|
||||
[](https://pkg.go.dev/github.com/gookit/color?tab=overview)
|
||||
[](https://github.com/gookit/color)
|
||||
[](https://travis-ci.org/gookit/color)
|
||||
[](https://coveralls.io/github/gookit/color?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/gookit/color)
|
||||
|
||||
Golang下的命令行色彩使用库, 拥有丰富的色彩渲染输出,通用的API方法,兼容Windows系统
|
||||
|
||||
> **[EN README](README.md)**
|
||||
|
||||
基本颜色预览:
|
||||
|
||||

|
||||
|
||||
现在,256色和RGB色彩也已经支持windows CMD和PowerShell中工作:
|
||||
|
||||

|
||||
|
||||
## 功能特色
|
||||
|
||||
- 使用简单方便,无其他依赖
|
||||
- 支持丰富的颜色输出, 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`
|
||||
|
||||

|
||||
|
||||
## 构建风格
|
||||
|
||||
```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`
|
||||
|
||||

|
||||
|
||||
## 扩展风格方法
|
||||
|
||||
> 支持在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`
|
||||
|
||||

|
||||
|
||||
### 简约提示风格
|
||||
|
||||
```go
|
||||
color.Info.Tips("tips style message")
|
||||
color.Warn.Tips("tips style message")
|
||||
```
|
||||
|
||||
Run demo: `go run ./_examples/theme_tips.go`
|
||||
|
||||

|
||||
|
||||
### 着重提示风格
|
||||
|
||||
```go
|
||||
color.Info.Prompt("prompt style message")
|
||||
color.Warn.Prompt("prompt style message")
|
||||
```
|
||||
|
||||
Run demo: `go run ./_examples/theme_prompt.go`
|
||||
|
||||

|
||||
|
||||
### 强调提示风格
|
||||
|
||||
```go
|
||||
color.Info.Block("prompt style message")
|
||||
color.Warn.Block("prompt style message")
|
||||
```
|
||||
|
||||
Run demo: `go run ./_examples/theme_block.go`
|
||||
|
||||

|
||||
|
||||
### 使用颜色标签
|
||||
|
||||
> **支持** 在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`
|
||||
|
||||

|
||||
|
||||
## 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`
|
||||
|
||||

|
||||
|
||||
## RGB色彩使用
|
||||
|
||||
> RGB色彩在 `v1.2.4` 后支持 Windows `CMD`, `PowerShell` 环境
|
||||
|
||||
**效果预览:**
|
||||
|
||||
> 运行 demo: `Run demo: go run ./_examples/color_rgb.go`
|
||||
|
||||

|
||||
|
||||
代码示例:
|
||||
|
||||
```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
272
vendor/github.com/gookit/color/color.go
generated
vendored
Normal 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
300
vendor/github.com/gookit/color/color_16.go
generated
vendored
Normal 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
218
vendor/github.com/gookit/color/color_256.go
generated
vendored
Normal 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[30–37m)
|
||||
8- 15:高强度颜色(同 ESC[90–97m)
|
||||
16-231:6 × 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
23
vendor/github.com/gookit/color/color_nonwin.go
generated
vendored
Normal 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
301
vendor/github.com/gookit/color/color_rgb.go
generated
vendored
Normal 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
152
vendor/github.com/gookit/color/color_windows.go
generated
vendored
Normal 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
5
vendor/github.com/gookit/color/go.mod
generated
vendored
Normal 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
22
vendor/github.com/gookit/color/go.sum
generated
vendored
Normal 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
307
vendor/github.com/gookit/color/rgb_to_256.go
generated
vendored
Normal 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
285
vendor/github.com/gookit/color/style.go
generated
vendored
Normal 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
310
vendor/github.com/gookit/color/tag.go
generated
vendored
Normal 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
351
vendor/github.com/gookit/color/utils.go
generated
vendored
Normal 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
28
vendor/github.com/gosuri/uilive/.travis.yml
generated
vendored
Normal 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
10
vendor/github.com/gosuri/uilive/LICENSE
generated
vendored
Normal 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
7
vendor/github.com/gosuri/uilive/Makefile
generated
vendored
Normal 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
31
vendor/github.com/gosuri/uilive/README.md
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# uilive [](https://godoc.org/github.com/gosuri/uilive) [](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
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ go get -v github.com/gosuri/uilive
|
||||
```
|
||||
2
vendor/github.com/gosuri/uilive/doc.go
generated
vendored
Normal file
2
vendor/github.com/gosuri/uilive/doc.go
generated
vendored
Normal 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
3
vendor/github.com/gosuri/uilive/go.mod
generated
vendored
Normal 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
37
vendor/github.com/gosuri/uilive/terminal_size.go
generated
vendored
Normal 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)
|
||||
}
|
||||
24
vendor/github.com/gosuri/uilive/terminal_size_windows.go
generated
vendored
Normal file
24
vendor/github.com/gosuri/uilive/terminal_size_windows.go
generated
vendored
Normal 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
173
vendor/github.com/gosuri/uilive/writer.go
generated
vendored
Normal 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
15
vendor/github.com/gosuri/uilive/writer_posix.go
generated
vendored
Normal 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
74
vendor/github.com/gosuri/uilive/writer_windows.go
generated
vendored
Normal 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
8
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal 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
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
27
vendor/github.com/mattn/go-runewidth/README.mkd
generated
vendored
Normal file
27
vendor/github.com/mattn/go-runewidth/README.mkd
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
go-runewidth
|
||||
============
|
||||
|
||||
[](https://travis-ci.org/mattn/go-runewidth)
|
||||
[](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD)
|
||||
[](http://godoc.org/github.com/mattn/go-runewidth)
|
||||
[](https://goreportcard.com/report/github.com/mattn/go-runewidth)
|
||||
|
||||
Provides functions to get fixed width of the character or string.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```go
|
||||
runewidth.StringWidth("つのだ☆HIRO") == 12
|
||||
```
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
Yasuhiro Matsumoto
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
under the MIT License: http://mattn.mit-license.org/2013
|
||||
3
vendor/github.com/mattn/go-runewidth/go.mod
generated
vendored
Normal file
3
vendor/github.com/mattn/go-runewidth/go.mod
generated
vendored
Normal 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
258
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
Normal 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)
|
||||
}
|
||||
8
vendor/github.com/mattn/go-runewidth/runewidth_appengine.go
generated
vendored
Normal file
8
vendor/github.com/mattn/go-runewidth/runewidth_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// +build appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
return false
|
||||
}
|
||||
9
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
9
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build js
|
||||
// +build !appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
func IsEastAsian() bool {
|
||||
// TODO: Implement this for the web. Detect east asian in a compatible way, and return true.
|
||||
return false
|
||||
}
|
||||
79
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
79
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal 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
427
vendor/github.com/mattn/go-runewidth/runewidth_table.go
generated
vendored
Normal 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},
|
||||
}
|
||||
28
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
28
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// +build windows
|
||||
// +build !appengine
|
||||
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
||||
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
|
||||
)
|
||||
|
||||
// IsEastAsian return true if the current locale is CJK
|
||||
func IsEastAsian() bool {
|
||||
r1, _, _ := procGetConsoleOutputCP.Call()
|
||||
if r1 == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch int(r1) {
|
||||
case 932, 51932, 936, 949, 950:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
21
vendor/github.com/mitchellh/go-glint/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mitchellh/go-glint/LICENSE
generated
vendored
Normal 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
79
vendor/github.com/mitchellh/go-glint/README.md
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# go-glint [](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:
|
||||
|
||||

|
||||
|
||||
## 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
89
vendor/github.com/mitchellh/go-glint/component.go
generated
vendored
Normal 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 }
|
||||
38
vendor/github.com/mitchellh/go-glint/components/progress.go
generated
vendored
Normal file
38
vendor/github.com/mitchellh/go-glint/components/progress.go
generated
vendored
Normal 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()
|
||||
})
|
||||
}
|
||||
112
vendor/github.com/mitchellh/go-glint/components/sparkline.go
generated
vendored
Normal file
112
vendor/github.com/mitchellh/go-glint/components/sparkline.go
generated
vendored
Normal 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',
|
||||
}
|
||||
36
vendor/github.com/mitchellh/go-glint/components/spinner.go
generated
vendored
Normal file
36
vendor/github.com/mitchellh/go-glint/components/spinner.go
generated
vendored
Normal 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())
|
||||
}
|
||||
23
vendor/github.com/mitchellh/go-glint/components/stopwatch.go
generated
vendored
Normal file
23
vendor/github.com/mitchellh/go-glint/components/stopwatch.go
generated
vendored
Normal 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
18
vendor/github.com/mitchellh/go-glint/context.go
generated
vendored
Normal 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
317
vendor/github.com/mitchellh/go-glint/document.go
generated
vendored
Normal 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
19
vendor/github.com/mitchellh/go-glint/finalize.go
generated
vendored
Normal 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
31
vendor/github.com/mitchellh/go-glint/flex/LICENSE
generated
vendored
Normal 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
33
vendor/github.com/mitchellh/go-glint/flex/PATENTS
generated
vendored
Normal 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
27
vendor/github.com/mitchellh/go-glint/flex/README.md
generated
vendored
Normal 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
454
vendor/github.com/mitchellh/go-glint/flex/enums.go
generated
vendored
Normal 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
73
vendor/github.com/mitchellh/go-glint/flex/math.go
generated
vendored
Normal 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
199
vendor/github.com/mitchellh/go-glint/flex/print.go
generated
vendored
Normal 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
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
37
vendor/github.com/mitchellh/go-glint/flex/yoga_h.go
generated
vendored
Normal 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
615
vendor/github.com/mitchellh/go-glint/flex/yoga_props.go
generated
vendored
Normal 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
14
vendor/github.com/mitchellh/go-glint/fragment.go
generated
vendored
Normal 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
15
vendor/github.com/mitchellh/go-glint/go.mod
generated
vendored
Normal 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
51
vendor/github.com/mitchellh/go-glint/go.sum
generated
vendored
Normal 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=
|
||||
42
vendor/github.com/mitchellh/go-glint/internal/layout/builder.go
generated
vendored
Normal file
42
vendor/github.com/mitchellh/go-glint/internal/layout/builder.go
generated
vendored
Normal 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
72
vendor/github.com/mitchellh/go-glint/layout.go
generated
vendored
Normal 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
199
vendor/github.com/mitchellh/go-glint/measure.go
generated
vendored
Normal 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
54
vendor/github.com/mitchellh/go-glint/renderer.go
generated
vendored
Normal 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
103
vendor/github.com/mitchellh/go-glint/renderer_string.go
generated
vendored
Normal 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
126
vendor/github.com/mitchellh/go-glint/renderer_term.go
generated
vendored
Normal 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
152
vendor/github.com/mitchellh/go-glint/style.go
generated
vendored
Normal 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
19
vendor/github.com/mitchellh/go-glint/testing.go
generated
vendored
Normal 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
37
vendor/github.com/mitchellh/go-glint/text.go
generated
vendored
Normal 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
87
vendor/github.com/mitchellh/go-glint/tree.go
generated
vendored
Normal 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
|
||||
}
|
||||
1
vendor/github.com/mitchellh/go-testing-interface/.travis.yml
generated
vendored
1
vendor/github.com/mitchellh/go-testing-interface/.travis.yml
generated
vendored
@@ -1,7 +1,6 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.8
|
||||
- 1.x
|
||||
- tip
|
||||
|
||||
|
||||
8
vendor/github.com/mitchellh/go-testing-interface/README.md
generated
vendored
8
vendor/github.com/mitchellh/go-testing-interface/README.md
generated
vendored
@@ -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?**
|
||||
|
||||
2
vendor/github.com/mitchellh/go-testing-interface/go.mod
generated
vendored
2
vendor/github.com/mitchellh/go-testing-interface/go.mod
generated
vendored
@@ -1 +1,3 @@
|
||||
module github.com/mitchellh/go-testing-interface
|
||||
|
||||
go 1.14
|
||||
|
||||
35
vendor/github.com/mitchellh/go-testing-interface/testing.go
generated
vendored
35
vendor/github.com/mitchellh/go-testing-interface/testing.go
generated
vendored
@@ -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()) {}
|
||||
|
||||
108
vendor/github.com/mitchellh/go-testing-interface/testing_go19.go
generated
vendored
108
vendor/github.com/mitchellh/go-testing-interface/testing_go19.go
generated
vendored
@@ -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() {}
|
||||
2
vendor/github.com/mitchellh/go-wordwrap/go.mod
generated
vendored
2
vendor/github.com/mitchellh/go-wordwrap/go.mod
generated
vendored
@@ -1 +1,3 @@
|
||||
module github.com/mitchellh/go-wordwrap
|
||||
|
||||
go 1.14
|
||||
|
||||
26
vendor/github.com/mitchellh/go-wordwrap/wordwrap.go
generated
vendored
26
vendor/github.com/mitchellh/go-wordwrap/wordwrap.go
generated
vendored
@@ -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
Reference in New Issue
Block a user