mirror of
https://github.com/schollz/croc.git
synced 2025-10-11 05:11:06 +02:00
Updated dependencies
This commit is contained in:
parent
caa7e7797e
commit
e24d37db7d
46 changed files with 7 additions and 1751 deletions
26
Gopkg.lock
generated
26
Gopkg.lock
generated
|
@ -7,30 +7,12 @@
|
|||
packages = ["."]
|
||||
revision = "77ed807830b4df581417e7f89eb81d4872832b72"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gosuri/uilive"
|
||||
packages = ["."]
|
||||
revision = "ac356e6e42cd31fcef8e6aec13ae9ed6fe87713e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gosuri/uiprogress"
|
||||
packages = [".","util/strutil"]
|
||||
revision = "d0567a9d84a1c40dd7568115ea66f4887bf57b33"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mars9/crypt"
|
||||
packages = ["."]
|
||||
revision = "65899cf653ff022fe5c7fe504b439feed9e7e0fc"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
|
@ -43,6 +25,12 @@
|
|||
packages = ["."]
|
||||
revision = "15c9654387fad6d257aa28f9be57b9f124101955"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/schollz/progressbar"
|
||||
packages = ["."]
|
||||
revision = "91090f7acee17a22f3cefcac2178c417b2ead337"
|
||||
version = "v0.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
|
@ -76,6 +64,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "56157cf168219ec6f5596364497dc7fc93cb674ce0a159fd339d88d025f97e25"
|
||||
inputs-digest = "bdbf624014ff879def63602194ddf9c775d9d8461e0b2e687314dc8b855ffc50"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
7
vendor/github.com/gosuri/uilive/.travis.yml
generated
vendored
7
vendor/github.com/gosuri/uilive/.travis.yml
generated
vendored
|
@ -1,7 +0,0 @@
|
|||
language: go
|
||||
sudo: false
|
||||
install:
|
||||
- go get ./...
|
||||
go:
|
||||
- 1.4
|
||||
- tip
|
10
vendor/github.com/gosuri/uilive/LICENSE
generated
vendored
10
vendor/github.com/gosuri/uilive/LICENSE
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
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.
|
31
vendor/github.com/gosuri/uilive/README.md
generated
vendored
31
vendor/github.com/gosuri/uilive/README.md
generated
vendored
|
@ -1,31 +0,0 @@
|
|||
# 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
2
vendor/github.com/gosuri/uilive/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// 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
|
BIN
vendor/github.com/gosuri/uilive/doc/example.gif
generated
vendored
BIN
vendor/github.com/gosuri/uilive/doc/example.gif
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 156 KiB |
26
vendor/github.com/gosuri/uilive/example/main.go
generated
vendored
26
vendor/github.com/gosuri/uilive/example/main.go
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uilive"
|
||||
)
|
||||
|
||||
func main() {
|
||||
writer := uilive.New()
|
||||
|
||||
// start listening for updates and render
|
||||
writer.Start()
|
||||
|
||||
for _, f := range []string{"Foo.zip", "Bar.iso"} {
|
||||
for i := 0; i <= 50; i++ {
|
||||
fmt.Fprintf(writer, "Downloading %s.. (%d/%d) GB\n", f, i, 50)
|
||||
time.Sleep(time.Millisecond * 25)
|
||||
}
|
||||
fmt.Fprintf(writer.Bypass(), "Downloaded %s\n", f)
|
||||
}
|
||||
|
||||
fmt.Fprintln(writer, "Finished: Downloaded 100GB")
|
||||
writer.Stop() // flush and stop rendering
|
||||
}
|
23
vendor/github.com/gosuri/uilive/example_test.go
generated
vendored
23
vendor/github.com/gosuri/uilive/example_test.go
generated
vendored
|
@ -1,23 +0,0 @@
|
|||
package uilive_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uilive"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
writer := uilive.New()
|
||||
|
||||
// start listening to 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
|
||||
}
|
138
vendor/github.com/gosuri/uilive/writer.go
generated
vendored
138
vendor/github.com/gosuri/uilive/writer.go
generated
vendored
|
@ -1,138 +0,0 @@
|
|||
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
|
||||
|
||||
// Out is the default output writer for the Writer
|
||||
var Out = 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
|
||||
}
|
||||
|
||||
// New returns a new Writer with defaults
|
||||
func New() *Writer {
|
||||
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 is buffer is empty
|
||||
if len(w.buf.Bytes()) == 0 {
|
||||
return nil
|
||||
}
|
||||
w.clearLines()
|
||||
|
||||
lines := 0
|
||||
for _, b := range w.buf.Bytes() {
|
||||
if b == '\n' {
|
||||
lines++
|
||||
}
|
||||
}
|
||||
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, 1)
|
||||
}
|
||||
|
||||
go w.Listen()
|
||||
}
|
||||
|
||||
// Stop stops the listener that updates the terminal
|
||||
func (w *Writer) Stop() {
|
||||
w.Flush()
|
||||
close(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()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write save the contents of b to its buffers. The only errors returned are ones encountered while writing to the underlying buffer.
|
||||
func (w *Writer) Write(b []byte) (n int, err error) {
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
return w.buf.Write(b)
|
||||
}
|
||||
|
||||
// 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) (n int, err error) {
|
||||
b.writer.mtx.Lock()
|
||||
defer b.writer.mtx.Unlock()
|
||||
|
||||
b.writer.clearLines()
|
||||
b.writer.lineCount = 0
|
||||
return b.writer.Out.Write(p)
|
||||
}
|
14
vendor/github.com/gosuri/uilive/writer_posix.go
generated
vendored
14
vendor/github.com/gosuri/uilive/writer_posix.go
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package uilive
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (w *Writer) clearLines() {
|
||||
for i := 0; i < w.lineCount; i++ {
|
||||
fmt.Fprintf(w.Out, "%c[2K", ESC) // clear the line
|
||||
fmt.Fprintf(w.Out, "%c[%dA", ESC, 1) // move the cursor up
|
||||
}
|
||||
}
|
24
vendor/github.com/gosuri/uilive/writer_test.go
generated
vendored
24
vendor/github.com/gosuri/uilive/writer_test.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
package uilive
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWriter(t *testing.T) {
|
||||
w := New()
|
||||
b := &bytes.Buffer{}
|
||||
w.Out = b
|
||||
w.Start()
|
||||
for i := 0; i < 2; i++ {
|
||||
fmt.Fprintln(w, "foo")
|
||||
}
|
||||
w.Stop()
|
||||
fmt.Fprintln(b, "bar")
|
||||
|
||||
want := "foo\nfoo\nbar\n"
|
||||
if b.String() != want {
|
||||
t.Fatalf("want %q, got %q", want, b.String())
|
||||
}
|
||||
}
|
74
vendor/github.com/gosuri/uilive/writer_windows.go
generated
vendored
74
vendor/github.com/gosuri/uilive/writer_windows.go
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package uilive
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mattn/go-isatty"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
var (
|
||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
|
||||
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
|
||||
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
|
||||
)
|
||||
|
||||
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 {
|
||||
for i := 0; i < w.lineCount; i++ {
|
||||
fmt.Fprintf(w.Out, "%c[%dA", ESC, 0) // move the cursor up
|
||||
fmt.Fprintf(w.Out, "%c[2K\r", ESC) // clear the line
|
||||
}
|
||||
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)))
|
||||
}
|
||||
}
|
7
vendor/github.com/gosuri/uiprogress/.travis.yml
generated
vendored
7
vendor/github.com/gosuri/uiprogress/.travis.yml
generated
vendored
|
@ -1,7 +0,0 @@
|
|||
language: go
|
||||
sudo: false
|
||||
install:
|
||||
- go get ./...
|
||||
go:
|
||||
- 1.4
|
||||
- tip
|
10
vendor/github.com/gosuri/uiprogress/LICENSE
generated
vendored
10
vendor/github.com/gosuri/uiprogress/LICENSE
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
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.
|
11
vendor/github.com/gosuri/uiprogress/Makefile
generated
vendored
11
vendor/github.com/gosuri/uiprogress/Makefile
generated
vendored
|
@ -1,11 +0,0 @@
|
|||
test:
|
||||
@go test -race .
|
||||
@go test -race ./util/strutil
|
||||
|
||||
examples:
|
||||
go run -race example/full/full.go
|
||||
go run -race example/incr/incr.go
|
||||
go run -race example/multi/multi.go
|
||||
go run -race example/simple/simple.go
|
||||
|
||||
.PHONY: test examples
|
146
vendor/github.com/gosuri/uiprogress/README.md
generated
vendored
146
vendor/github.com/gosuri/uiprogress/README.md
generated
vendored
|
@ -1,146 +0,0 @@
|
|||
# uiprogress [](https://godoc.org/github.com/gosuri/uiprogress) [](https://travis-ci.org/gosuri/uiprogress)
|
||||
|
||||
A Go library to render progress bars in terminal applications. It provides a set of flexible features with a customizable API.
|
||||
|
||||

|
||||
|
||||
Progress bars improve readability for terminal applications with long outputs by providing a concise feedback loop.
|
||||
|
||||
## Features
|
||||
|
||||
* __Multiple Bars__: uiprogress can render multiple progress bars that can be tracked concurrently
|
||||
* __Dynamic Addition__: Add additional progress bars any time, even after the progress tracking has started
|
||||
* __Prepend and Append Functions__: Append or prepend completion percent and time elapsed to the progress bars
|
||||
* __Custom Decorator Functions__: Add custom functions around the bar along with helper functions
|
||||
|
||||
## Usage
|
||||
|
||||
To start listening for progress bars, call `uiprogress.Start()` and add a progress bar using `uiprogress.AddBar(total int)`. Update the progress using `bar.Incr()` or `bar.Set(n int)`. Full source code for the below example is available at [example/simple/simple.go](example/simple/simple.go)
|
||||
|
||||
```go
|
||||
uiprogress.Start() // start rendering
|
||||
bar := uiprogress.AddBar(100) // Add a new bar
|
||||
|
||||
// optionally, append and prepend completion and elapsed time
|
||||
bar.AppendCompleted()
|
||||
bar.PrependElapsed()
|
||||
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond * 20)
|
||||
}
|
||||
```
|
||||
|
||||
This will render the below in the terminal
|
||||
|
||||

|
||||
|
||||
### Using Custom Decorators
|
||||
|
||||
You can also add a custom decorator function in addition to default `bar.AppendCompleted()` and `bar.PrependElapsed()` decorators. The below example tracks the current step for an application deploy progress. Source code for the below example is available at [example/full/full.go](example/full/full.go)
|
||||
|
||||
```go
|
||||
var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
|
||||
bar := uiprogress.AddBar(len(steps))
|
||||
|
||||
// prepend the current step to the bar
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return "app: " + steps[b.Current()-1]
|
||||
})
|
||||
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
```
|
||||
|
||||
### Rendering Multiple bars
|
||||
|
||||
You can add multiple bars using `uiprogress.AddBar(n)`. The below example demonstrates updating multiple bars concurrently and adding a new bar later in the pipeline. Source for this example is available at [example/multi/multi.go](example/multi/multi.go)
|
||||
|
||||
```go
|
||||
waitTime := time.Millisecond * 100
|
||||
uiprogress.Start()
|
||||
|
||||
// start the progress bars in go routines
|
||||
var wg sync.WaitGroup
|
||||
|
||||
bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar1.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar2.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 1; i <= bar3.Total; i++ {
|
||||
bar3.Set(i)
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
// wait for all the go routines to finish
|
||||
wg.Wait()
|
||||
```
|
||||
|
||||
This will produce
|
||||
|
||||

|
||||
|
||||
### `Incr` counter
|
||||
|
||||
[Bar.Incr()](https://godoc.org/github.com/gosuri/uiprogress#Bar.Incr) is an atomic counter and can be used as a general tracker, making it ideal for tracking progress of work fanned out to a lots of go routines. The source code for the below example is available at [example/incr/incr.go](example/incr/incr.go)
|
||||
|
||||
```go
|
||||
runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores
|
||||
|
||||
// create a new bar and prepend the task progress to the bar and fanout into 1k go routines
|
||||
count := 1000
|
||||
bar := uiprogress.AddBar(count).AppendCompleted().PrependElapsed()
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
|
||||
})
|
||||
|
||||
uiprogress.Start()
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// fanout into go routines
|
||||
for i := 0; i < count; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
|
||||
bar.Incr()
|
||||
}()
|
||||
}
|
||||
time.Sleep(time.Second) // wait for a second for all the go routines to finish
|
||||
wg.Wait()
|
||||
uiprogress.Stop()
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ go get -v github.com/gosuri/uiprogress
|
||||
```
|
||||
## Todos
|
||||
|
||||
- [ ] Resize bars and decorators by auto detecting window's dimensions
|
||||
- [ ] Handle more progress bars than vertical screen allows
|
||||
|
||||
## License
|
||||
|
||||
uiprogress is released under the MIT License. See [LICENSE](https://github.com/gosuri/uiprogress/blob/master/LICENSE).
|
237
vendor/github.com/gosuri/uiprogress/bar.go
generated
vendored
237
vendor/github.com/gosuri/uiprogress/bar.go
generated
vendored
|
@ -1,237 +0,0 @@
|
|||
package uiprogress
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress/util/strutil"
|
||||
)
|
||||
|
||||
var (
|
||||
// Fill is the default character representing completed progress
|
||||
Fill byte = '='
|
||||
|
||||
// Head is the default character that moves when progress is updated
|
||||
Head byte = '>'
|
||||
|
||||
// Empty is the default character that represents the empty progress
|
||||
Empty byte = '-'
|
||||
|
||||
// LeftEnd is the default character in the left most part of the progress indicator
|
||||
LeftEnd byte = '['
|
||||
|
||||
// RightEnd is the default character in the right most part of the progress indicator
|
||||
RightEnd byte = ']'
|
||||
|
||||
// Width is the default width of the progress bar
|
||||
Width = 70
|
||||
|
||||
// ErrMaxCurrentReached is error when trying to set current value that exceeds the total value
|
||||
ErrMaxCurrentReached = errors.New("errors: current value is greater total value")
|
||||
)
|
||||
|
||||
// Bar represents a progress bar
|
||||
type Bar struct {
|
||||
// Total of the total for the progress bar
|
||||
Total int
|
||||
|
||||
// LeftEnd is character in the left most part of the progress indicator. Defaults to '['
|
||||
LeftEnd byte
|
||||
|
||||
// RightEnd is character in the right most part of the progress indicator. Defaults to ']'
|
||||
RightEnd byte
|
||||
|
||||
// Fill is the character representing completed progress. Defaults to '='
|
||||
Fill byte
|
||||
|
||||
// Head is the character that moves when progress is updated. Defaults to '>'
|
||||
Head byte
|
||||
|
||||
// Empty is the character that represents the empty progress. Default is '-'
|
||||
Empty byte
|
||||
|
||||
// TimeStated is time progress began
|
||||
TimeStarted time.Time
|
||||
|
||||
// Width is the width of the progress bar
|
||||
Width int
|
||||
|
||||
// timeElased is the time elapsed for the progress
|
||||
timeElapsed time.Duration
|
||||
current int
|
||||
|
||||
mtx *sync.RWMutex
|
||||
|
||||
appendFuncs []DecoratorFunc
|
||||
prependFuncs []DecoratorFunc
|
||||
}
|
||||
|
||||
// DecoratorFunc is a function that can be prepended and appended to the progress bar
|
||||
type DecoratorFunc func(b *Bar) string
|
||||
|
||||
// NewBar returns a new progress bar
|
||||
func NewBar(total int) *Bar {
|
||||
return &Bar{
|
||||
Total: total,
|
||||
Width: Width,
|
||||
LeftEnd: LeftEnd,
|
||||
RightEnd: RightEnd,
|
||||
Head: Head,
|
||||
Fill: Fill,
|
||||
Empty: Empty,
|
||||
|
||||
mtx: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// Set the current count of the bar. It returns ErrMaxCurrentReached when trying n exceeds the total value. This is atomic operation and concurancy safe.
|
||||
func (b *Bar) Set(n int) error {
|
||||
b.mtx.Lock()
|
||||
defer b.mtx.Unlock()
|
||||
|
||||
if n > b.Total {
|
||||
return ErrMaxCurrentReached
|
||||
}
|
||||
b.current = n
|
||||
return nil
|
||||
}
|
||||
|
||||
// Incr increments the current value by 1, time elapsed to current time and returns true. It returns false if the cursor has reached or exceeds total value.
|
||||
func (b *Bar) Incr() bool {
|
||||
b.mtx.Lock()
|
||||
defer b.mtx.Unlock()
|
||||
|
||||
n := b.current + 1
|
||||
if n > b.Total {
|
||||
return false
|
||||
}
|
||||
var t time.Time
|
||||
if b.TimeStarted == t {
|
||||
b.TimeStarted = time.Now()
|
||||
}
|
||||
b.timeElapsed = time.Since(b.TimeStarted)
|
||||
b.current = n
|
||||
return true
|
||||
}
|
||||
|
||||
// Current returns the current progress of the bar
|
||||
func (b *Bar) Current() int {
|
||||
b.mtx.RLock()
|
||||
defer b.mtx.RUnlock()
|
||||
return b.current
|
||||
}
|
||||
|
||||
// AppendFunc runs the decorator function and renders the output on the right of the progress bar
|
||||
func (b *Bar) AppendFunc(f DecoratorFunc) *Bar {
|
||||
b.mtx.Lock()
|
||||
defer b.mtx.Unlock()
|
||||
b.appendFuncs = append(b.appendFuncs, f)
|
||||
return b
|
||||
}
|
||||
|
||||
// AppendCompleted appends the completion percent to the progress bar
|
||||
func (b *Bar) AppendCompleted() *Bar {
|
||||
b.AppendFunc(func(b *Bar) string {
|
||||
return b.CompletedPercentString()
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
// AppendElapsed appends the time elapsed the be progress bar
|
||||
func (b *Bar) AppendElapsed() *Bar {
|
||||
b.AppendFunc(func(b *Bar) string {
|
||||
return strutil.PadLeft(b.TimeElapsedString(), 5, ' ')
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
// PrependFunc runs decorator function and render the output left the progress bar
|
||||
func (b *Bar) PrependFunc(f DecoratorFunc) *Bar {
|
||||
b.mtx.Lock()
|
||||
defer b.mtx.Unlock()
|
||||
b.prependFuncs = append(b.prependFuncs, f)
|
||||
return b
|
||||
}
|
||||
|
||||
// PrependCompleted prepends the precent completed to the progress bar
|
||||
func (b *Bar) PrependCompleted() *Bar {
|
||||
b.PrependFunc(func(b *Bar) string {
|
||||
return b.CompletedPercentString()
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
// PrependElapsed prepends the time elapsed to the begining of the bar
|
||||
func (b *Bar) PrependElapsed() *Bar {
|
||||
b.PrependFunc(func(b *Bar) string {
|
||||
return strutil.PadLeft(b.TimeElapsedString(), 5, ' ')
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
// Bytes returns the byte presentation of the progress bar
|
||||
func (b *Bar) Bytes() []byte {
|
||||
completedWidth := int(float64(b.Width) * (b.CompletedPercent() / 100.00))
|
||||
|
||||
// add fill and empty bits
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < completedWidth; i++ {
|
||||
buf.WriteByte(b.Fill)
|
||||
}
|
||||
for i := 0; i < b.Width-completedWidth; i++ {
|
||||
buf.WriteByte(b.Empty)
|
||||
}
|
||||
|
||||
// set head bit
|
||||
pb := buf.Bytes()
|
||||
if completedWidth > 0 && completedWidth < b.Width {
|
||||
pb[completedWidth-1] = b.Head
|
||||
}
|
||||
|
||||
// set left and right ends bits
|
||||
pb[0], pb[len(pb)-1] = b.LeftEnd, b.RightEnd
|
||||
|
||||
// render append functions to the right of the bar
|
||||
for _, f := range b.appendFuncs {
|
||||
pb = append(pb, ' ')
|
||||
pb = append(pb, []byte(f(b))...)
|
||||
}
|
||||
|
||||
// render prepend functions to the left of the bar
|
||||
for _, f := range b.prependFuncs {
|
||||
args := []byte(f(b))
|
||||
args = append(args, ' ')
|
||||
pb = append(args, pb...)
|
||||
}
|
||||
return pb
|
||||
}
|
||||
|
||||
// String returns the string representation of the bar
|
||||
func (b *Bar) String() string {
|
||||
return string(b.Bytes())
|
||||
}
|
||||
|
||||
// CompletedPercent return the percent completed
|
||||
func (b *Bar) CompletedPercent() float64 {
|
||||
return (float64(b.Current()) / float64(b.Total)) * 100.00
|
||||
}
|
||||
|
||||
// CompletedPercentString returns the formatted string representation of the completed percent
|
||||
func (b *Bar) CompletedPercentString() string {
|
||||
return fmt.Sprintf("%3.f%%", b.CompletedPercent())
|
||||
}
|
||||
|
||||
// TimeElapsed returns the time elapsed
|
||||
func (b *Bar) TimeElapsed() time.Duration {
|
||||
b.mtx.RLock()
|
||||
defer b.mtx.RUnlock()
|
||||
return b.timeElapsed
|
||||
}
|
||||
|
||||
// TimeElapsedString returns the formatted string represenation of the time elapsed
|
||||
func (b *Bar) TimeElapsedString() string {
|
||||
return strutil.PrettyTime(b.TimeElapsed())
|
||||
}
|
37
vendor/github.com/gosuri/uiprogress/bar_test.go
generated
vendored
37
vendor/github.com/gosuri/uiprogress/bar_test.go
generated
vendored
|
@ -1,37 +0,0 @@
|
|||
package uiprogress
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBarPrepend(t *testing.T) {
|
||||
b := NewBar(100)
|
||||
b.PrependCompleted()
|
||||
b.Set(50)
|
||||
if !strings.Contains(b.String(), "50") {
|
||||
t.Fatal("want", "50%", "in", b.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBarIncr(t *testing.T) {
|
||||
b := NewBar(10000)
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 10000; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
b.Incr()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)))
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
if b.Current() != 10000 {
|
||||
t.Fatal("need", 10000, "got", b.Current())
|
||||
}
|
||||
}
|
2
vendor/github.com/gosuri/uiprogress/doc.go
generated
vendored
2
vendor/github.com/gosuri/uiprogress/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package uiprogress is a library to render progress bars in terminal applications
|
||||
package uiprogress
|
BIN
vendor/github.com/gosuri/uiprogress/doc/example_full.gif
generated
vendored
BIN
vendor/github.com/gosuri/uiprogress/doc/example_full.gif
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 674 KiB |
BIN
vendor/github.com/gosuri/uiprogress/doc/example_multi.gif
generated
vendored
BIN
vendor/github.com/gosuri/uiprogress/doc/example_multi.gif
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 784 KiB |
BIN
vendor/github.com/gosuri/uiprogress/doc/example_simple.gif
generated
vendored
BIN
vendor/github.com/gosuri/uiprogress/doc/example_simple.gif
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 230 KiB |
50
vendor/github.com/gosuri/uiprogress/example/bypass/bypass.go
generated
vendored
50
vendor/github.com/gosuri/uiprogress/example/bypass/bypass.go
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
)
|
||||
|
||||
func main() {
|
||||
waitTime := time.Millisecond * 200
|
||||
p := uiprogress.New()
|
||||
p.Start()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
bar1 := p.AddBar(20).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar1.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
fmt.Fprintln(p.Bypass(), "Bar1 finished")
|
||||
}()
|
||||
|
||||
bar2 := p.AddBar(40).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar2.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
fmt.Fprintln(p.Bypass(), "Bar2 finished")
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
bar3 := p.AddBar(20).PrependElapsed().AppendCompleted()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar3.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
fmt.Fprintln(p.Bypass(), "Bar3 finished")
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
51
vendor/github.com/gosuri/uiprogress/example/full/full.go
generated
vendored
51
vendor/github.com/gosuri/uiprogress/example/full/full.go
generated
vendored
|
@ -1,51 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
"github.com/gosuri/uiprogress/util/strutil"
|
||||
)
|
||||
|
||||
var steps = []string{
|
||||
"downloading source",
|
||||
"installing deps",
|
||||
"compiling",
|
||||
"packaging",
|
||||
"seeding database",
|
||||
"deploying",
|
||||
"staring servers",
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("apps: deployment started: app1, app2")
|
||||
uiprogress.Start()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go deploy("app1", &wg)
|
||||
wg.Add(1)
|
||||
go deploy("app2", &wg)
|
||||
wg.Wait()
|
||||
|
||||
fmt.Println("apps: successfully deployed: app1, app2")
|
||||
}
|
||||
|
||||
func deploy(app string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
bar := uiprogress.AddBar(len(steps)).AppendCompleted().PrependElapsed()
|
||||
bar.Width = 50
|
||||
|
||||
// prepend the deploy step to the bar
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return strutil.Resize(app+": "+steps[b.Current()-1], 22)
|
||||
})
|
||||
|
||||
rand.Seed(500)
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(2000)))
|
||||
}
|
||||
}
|
38
vendor/github.com/gosuri/uiprogress/example/incr/incr.go
generated
vendored
38
vendor/github.com/gosuri/uiprogress/example/incr/incr.go
generated
vendored
|
@ -1,38 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores
|
||||
|
||||
// create a new bar and prepend the task progress to the bar and fanout into 1k go routines
|
||||
count := 1000
|
||||
bar := uiprogress.AddBar(count).AppendCompleted().PrependElapsed()
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
|
||||
})
|
||||
|
||||
uiprogress.Start()
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// fanout into 1k go routines
|
||||
for i := 0; i < count; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
|
||||
bar.Incr()
|
||||
}()
|
||||
}
|
||||
time.Sleep(time.Second) // wait for a second for all the go routines to finish
|
||||
wg.Wait()
|
||||
uiprogress.Stop()
|
||||
}
|
45
vendor/github.com/gosuri/uiprogress/example/multi/multi.go
generated
vendored
45
vendor/github.com/gosuri/uiprogress/example/multi/multi.go
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
)
|
||||
|
||||
func main() {
|
||||
waitTime := time.Millisecond * 100
|
||||
uiprogress.Start()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar1.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar2.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar3.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
20
vendor/github.com/gosuri/uiprogress/example/simple/simple.go
generated
vendored
20
vendor/github.com/gosuri/uiprogress/example/simple/simple.go
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uiprogress.Start() // start rendering
|
||||
bar := uiprogress.AddBar(100) // Add a new bar
|
||||
|
||||
// optionally, append and prepend completion and elapsed time
|
||||
bar.AppendCompleted()
|
||||
bar.PrependElapsed()
|
||||
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond * 20)
|
||||
}
|
||||
}
|
103
vendor/github.com/gosuri/uiprogress/example_test.go
generated
vendored
103
vendor/github.com/gosuri/uiprogress/example_test.go
generated
vendored
|
@ -1,103 +0,0 @@
|
|||
package uiprogress_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uiprogress"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
uiprogress.Start() // start rendering
|
||||
bar := uiprogress.AddBar(100) // Add a new bar
|
||||
|
||||
// optionally, append and prepend completion and elapsed time
|
||||
bar.AppendCompleted()
|
||||
bar.PrependElapsed()
|
||||
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond * 20)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleProgress_AddBar() {
|
||||
waitTime := time.Millisecond * 100
|
||||
uiprogress.Start()
|
||||
// start the progress bars in go routines
|
||||
var wg sync.WaitGroup
|
||||
|
||||
bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar1.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for bar2.Incr() {
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := 1; i <= bar3.Total; i++ {
|
||||
bar3.Set(i)
|
||||
time.Sleep(waitTime)
|
||||
}
|
||||
}()
|
||||
// wait for all the go routines to finish
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func ExampleDecoratorFunc() {
|
||||
var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
|
||||
bar := uiprogress.AddBar(len(steps))
|
||||
|
||||
// prepend the current step to the bar
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return "app: " + steps[b.Current()-1]
|
||||
})
|
||||
|
||||
for bar.Incr() {
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleBar_Incr() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores
|
||||
|
||||
// create a new bar and prepend the task progress to the bar
|
||||
count := 1000
|
||||
bar := uiprogress.AddBar(count).AppendCompleted().PrependElapsed()
|
||||
bar.PrependFunc(func(b *uiprogress.Bar) string {
|
||||
return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
|
||||
})
|
||||
|
||||
uiprogress.Start()
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// fanout into 1k go routines
|
||||
for i := 0; i < count; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
|
||||
bar.Incr()
|
||||
}()
|
||||
}
|
||||
time.Sleep(time.Second) // wait for a second for all the go routines to finish
|
||||
wg.Wait()
|
||||
uiprogress.Stop()
|
||||
}
|
146
vendor/github.com/gosuri/uiprogress/progress.go
generated
vendored
146
vendor/github.com/gosuri/uiprogress/progress.go
generated
vendored
|
@ -1,146 +0,0 @@
|
|||
package uiprogress
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uilive"
|
||||
)
|
||||
|
||||
// Out is the default writer to render progress bars to
|
||||
var Out = os.Stdout
|
||||
|
||||
// RefreshInterval in the default time duration to wait for refreshing the output
|
||||
var RefreshInterval = time.Millisecond * 10
|
||||
|
||||
// defaultProgress is the default progress
|
||||
var defaultProgress = New()
|
||||
|
||||
// Progress represents the container that renders progress bars
|
||||
type Progress struct {
|
||||
// Out is the writer to render progress bars to
|
||||
Out io.Writer
|
||||
|
||||
// Width is the width of the progress bars
|
||||
Width int
|
||||
|
||||
// Bars is the collection of progress bars
|
||||
Bars []*Bar
|
||||
|
||||
// RefreshInterval in the time duration to wait for refreshing the output
|
||||
RefreshInterval time.Duration
|
||||
|
||||
lw *uilive.Writer
|
||||
ticker *time.Ticker
|
||||
tdone chan bool
|
||||
mtx *sync.RWMutex
|
||||
}
|
||||
|
||||
// New returns a new progress bar with defaults
|
||||
func New() *Progress {
|
||||
lw := uilive.New()
|
||||
lw.Out = Out
|
||||
|
||||
return &Progress{
|
||||
Width: Width,
|
||||
Out: Out,
|
||||
Bars: make([]*Bar, 0),
|
||||
RefreshInterval: RefreshInterval,
|
||||
|
||||
tdone: make(chan bool),
|
||||
lw: uilive.New(),
|
||||
mtx: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddBar creates a new progress bar and adds it to the default progress container
|
||||
func AddBar(total int) *Bar {
|
||||
return defaultProgress.AddBar(total)
|
||||
}
|
||||
|
||||
// Start starts the rendering the progress of progress bars using the DefaultProgress. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`
|
||||
func Start() {
|
||||
defaultProgress.Start()
|
||||
}
|
||||
|
||||
// Stop stops listening
|
||||
func Stop() {
|
||||
defaultProgress.Stop()
|
||||
}
|
||||
|
||||
// Listen listens for updates and renders the progress bars
|
||||
func Listen() {
|
||||
defaultProgress.Listen()
|
||||
}
|
||||
|
||||
func (p *Progress) SetOut(o io.Writer) {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
|
||||
p.Out = o
|
||||
p.lw.Out = o
|
||||
}
|
||||
|
||||
func (p *Progress) SetRefreshInterval(interval time.Duration) {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
p.RefreshInterval = interval
|
||||
}
|
||||
|
||||
// AddBar creates a new progress bar and adds to the container
|
||||
func (p *Progress) AddBar(total int) *Bar {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
|
||||
bar := NewBar(total)
|
||||
bar.Width = p.Width
|
||||
p.Bars = append(p.Bars, bar)
|
||||
return bar
|
||||
}
|
||||
|
||||
// Listen listens for updates and renders the progress bars
|
||||
func (p *Progress) Listen() {
|
||||
for {
|
||||
|
||||
p.mtx.Lock()
|
||||
interval := p.RefreshInterval
|
||||
p.mtx.Unlock()
|
||||
|
||||
select {
|
||||
case <-time.After(interval):
|
||||
p.print()
|
||||
case <-p.tdone:
|
||||
p.print()
|
||||
close(p.tdone)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Progress) print() {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
for _, bar := range p.Bars {
|
||||
fmt.Fprintln(p.lw, bar.String())
|
||||
}
|
||||
p.lw.Flush()
|
||||
}
|
||||
|
||||
// Start starts the rendering the progress of progress bars. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`
|
||||
func (p *Progress) Start() {
|
||||
go p.Listen()
|
||||
}
|
||||
|
||||
// Stop stops listening
|
||||
func (p *Progress) Stop() {
|
||||
p.tdone <- true
|
||||
<-p.tdone
|
||||
}
|
||||
|
||||
// Bypass returns a writer which allows non-buffered data to be written to the underlying output
|
||||
func (p *Progress) Bypass() io.Writer {
|
||||
return p.lw.Bypass()
|
||||
}
|
45
vendor/github.com/gosuri/uiprogress/progress_test.go
generated
vendored
45
vendor/github.com/gosuri/uiprogress/progress_test.go
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
package uiprogress
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestStoppingPrintout(t *testing.T) {
|
||||
progress := New()
|
||||
progress.SetRefreshInterval(time.Millisecond * 10)
|
||||
|
||||
var buffer = &bytes.Buffer{}
|
||||
progress.SetOut(buffer)
|
||||
|
||||
bar := progress.AddBar(100)
|
||||
progress.Start()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
for i := 0; i <= 80; i = i + 10 {
|
||||
bar.Set(i)
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
progress.Stop()
|
||||
fmt.Fprintf(buffer, "foo")
|
||||
|
||||
var wantSuffix = "[======================================================>-------------]\nfoo"
|
||||
|
||||
if !strings.HasSuffix(buffer.String(), wantSuffix) {
|
||||
t.Errorf("Content that should be printed after stop not appearing on buffer.")
|
||||
}
|
||||
}
|
61
vendor/github.com/gosuri/uiprogress/util/strutil/strutil.go
generated
vendored
61
vendor/github.com/gosuri/uiprogress/util/strutil/strutil.go
generated
vendored
|
@ -1,61 +0,0 @@
|
|||
// Package strutil provides various utilities for manipulating strings
|
||||
package strutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PadRight returns a new string of a specified length in which the end of the current string is padded with spaces or with a specified Unicode character.
|
||||
func PadRight(str string, length int, pad byte) string {
|
||||
if len(str) >= length {
|
||||
return str
|
||||
}
|
||||
buf := bytes.NewBufferString(str)
|
||||
for i := 0; i < length-len(str); i++ {
|
||||
buf.WriteByte(pad)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// PadLeft returns a new string of a specified length in which the beginning of the current string is padded with spaces or with a specified Unicode character.
|
||||
func PadLeft(str string, length int, pad byte) string {
|
||||
if len(str) >= length {
|
||||
return str
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < length-len(str); i++ {
|
||||
buf.WriteByte(pad)
|
||||
}
|
||||
buf.WriteString(str)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Resize resizes the string with the given length. It ellipses with '...' when the string's length exceeds
|
||||
// the desired length or pads spaces to the right of the string when length is smaller than desired
|
||||
func Resize(s string, length uint) string {
|
||||
n := int(length)
|
||||
if len(s) == n {
|
||||
return s
|
||||
}
|
||||
// Pads only when length of the string smaller than len needed
|
||||
s = PadRight(s, n, ' ')
|
||||
if len(s) > n {
|
||||
b := []byte(s)
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < n-3; i++ {
|
||||
buf.WriteByte(b[i])
|
||||
}
|
||||
buf.WriteString("...")
|
||||
s = buf.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// PrettyTime returns the string representation of the duration. It rounds the time duration to a second and returns a "---" when duration is 0
|
||||
func PrettyTime(t time.Duration) string {
|
||||
if t == 0 {
|
||||
return "---"
|
||||
}
|
||||
return (t - (t % time.Second)).String()
|
||||
}
|
42
vendor/github.com/gosuri/uiprogress/util/strutil/strutil_test.go
generated
vendored
42
vendor/github.com/gosuri/uiprogress/util/strutil/strutil_test.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
package strutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestResize(t *testing.T) {
|
||||
s := "foo"
|
||||
got := Resize(s, 5)
|
||||
if len(got) != 5 {
|
||||
t.Fatal("want", 5, "got", len(got))
|
||||
}
|
||||
s = "foobar"
|
||||
got = Resize(s, 5)
|
||||
|
||||
if got != "fo..." {
|
||||
t.Fatal("want", "fo...", "got", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPadRight(t *testing.T) {
|
||||
got := PadRight("foo", 5, '-')
|
||||
if got != "foo--" {
|
||||
t.Fatal("want", "foo--", "got", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPadLeft(t *testing.T) {
|
||||
got := PadLeft("foo", 5, '-')
|
||||
if got != "--foo" {
|
||||
t.Fatal("want", "--foo", "got", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrettyTime(t *testing.T) {
|
||||
d, _ := time.ParseDuration("")
|
||||
got := PrettyTime(d)
|
||||
if got != "---" {
|
||||
t.Fatal("want", "---", "got", got)
|
||||
}
|
||||
}
|
9
vendor/github.com/mattn/go-isatty/.travis.yml
generated
vendored
9
vendor/github.com/mattn/go-isatty/.travis.yml
generated
vendored
|
@ -1,9 +0,0 @@
|
|||
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 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5
|
9
vendor/github.com/mattn/go-isatty/LICENSE
generated
vendored
9
vendor/github.com/mattn/go-isatty/LICENSE
generated
vendored
|
@ -1,9 +0,0 @@
|
|||
Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
|
||||
|
||||
MIT License (Expat)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
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.
|
50
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
50
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
# go-isatty
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-isatty)
|
||||
[](https://travis-ci.org/mattn/go-isatty)
|
||||
[](https://coveralls.io/github/mattn/go-isatty?branch=master)
|
||||
[](https://goreportcard.com/report/mattn/go-isatty)
|
||||
|
||||
isatty for golang
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mattn/go-isatty"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Terminal")
|
||||
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Cygwin/MSYS2 Terminal")
|
||||
} else {
|
||||
fmt.Println("Is Not Terminal")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go get github.com/mattn/go-isatty
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
||||
|
||||
## Thanks
|
||||
|
||||
* k-takata: base idea for IsCygwinTerminal
|
||||
|
||||
https://github.com/k-takata/go-iscygpty
|
2
vendor/github.com/mattn/go-isatty/doc.go
generated
vendored
2
vendor/github.com/mattn/go-isatty/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package isatty implements interface to isatty
|
||||
package isatty
|
18
vendor/github.com/mattn/go-isatty/example_test.go
generated
vendored
18
vendor/github.com/mattn/go-isatty/example_test.go
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
package isatty_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Terminal")
|
||||
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Cygwin/MSYS2 Terminal")
|
||||
} else {
|
||||
fmt.Println("Is Not Terminal")
|
||||
}
|
||||
}
|
15
vendor/github.com/mattn/go-isatty/isatty_appengine.go
generated
vendored
15
vendor/github.com/mattn/go-isatty/isatty_appengine.go
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
// +build appengine
|
||||
|
||||
package isatty
|
||||
|
||||
// IsTerminal returns true if the file descriptor is terminal which
|
||||
// is always false on on appengine classic which is a sandboxed PaaS.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
18
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
18
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
18
vendor/github.com/mattn/go-isatty/isatty_linux.go
generated
vendored
18
vendor/github.com/mattn/go-isatty/isatty_linux.go
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
// +build linux
|
||||
// +build !appengine,!ppc64,!ppc64le
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
19
vendor/github.com/mattn/go-isatty/isatty_linux_ppc64x.go
generated
vendored
19
vendor/github.com/mattn/go-isatty/isatty_linux_ppc64x.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
syscall "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
10
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
10
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
// +build !windows
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
19
vendor/github.com/mattn/go-isatty/isatty_others_test.go
generated
vendored
19
vendor/github.com/mattn/go-isatty/isatty_others_test.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTerminal(t *testing.T) {
|
||||
// test for non-panic
|
||||
IsTerminal(os.Stdout.Fd())
|
||||
}
|
||||
|
||||
func TestCygwinPipeName(t *testing.T) {
|
||||
if IsCygwinTerminal(os.Stdout.Fd()) {
|
||||
t.Fatal("should be false always")
|
||||
}
|
||||
}
|
16
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
16
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
|
@ -1,16 +0,0 @@
|
|||
// +build solaris
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termio unix.Termio
|
||||
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
||||
return err == nil
|
||||
}
|
94
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
94
vendor/github.com/mattn/go-isatty/isatty_windows.go
generated
vendored
|
@ -1,94 +0,0 @@
|
|||
// +build windows
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
fileNameInfo uintptr = 2
|
||||
fileTypePipe = 3
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
|
||||
procGetFileType = kernel32.NewProc("GetFileType")
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Check if GetFileInformationByHandleEx is available.
|
||||
if procGetFileInformationByHandleEx.Find() != nil {
|
||||
procGetFileInformationByHandleEx = nil
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
}
|
||||
|
||||
// Check pipe name is used for cygwin/msys2 pty.
|
||||
// Cygwin/MSYS2 PTY has a name like:
|
||||
// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
|
||||
func isCygwinPipeName(name string) bool {
|
||||
token := strings.Split(name, "-")
|
||||
if len(token) < 5 {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[0] != `\msys` && token[0] != `\cygwin` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[1] == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(token[2], "pty") {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[3] != `from` && token[3] != `to` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[4] != "master" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
if procGetFileInformationByHandleEx == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Cygwin/msys's pty is a pipe.
|
||||
ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
|
||||
if ft != fileTypePipe || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var buf [2 + syscall.MAX_PATH]uint16
|
||||
r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
|
||||
4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
|
||||
uintptr(len(buf)*2), 0, 0)
|
||||
if r == 0 || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
l := *(*uint32)(unsafe.Pointer(&buf))
|
||||
return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
|
||||
}
|
35
vendor/github.com/mattn/go-isatty/isatty_windows_test.go
generated
vendored
35
vendor/github.com/mattn/go-isatty/isatty_windows_test.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCygwinPipeName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
result bool
|
||||
}{
|
||||
{``, false},
|
||||
{`\msys-`, false},
|
||||
{`\cygwin-----`, false},
|
||||
{`\msys-x-PTY5-pty1-from-master`, false},
|
||||
{`\cygwin-x-PTY5-from-master`, false},
|
||||
{`\cygwin-x-pty2-from-toaster`, false},
|
||||
{`\cygwin--pty2-from-master`, false},
|
||||
{`\\cygwin-x-pty2-from-master`, false},
|
||||
{`\cygwin-x-pty2-from-master-`, true}, // for the feature
|
||||
{`\cygwin-e022582115c10879-pty4-from-master`, true},
|
||||
{`\msys-e022582115c10879-pty4-to-master`, true},
|
||||
{`\cygwin-e022582115c10879-pty4-to-master`, true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
want := test.result
|
||||
got := isCygwinPipeName(test.name)
|
||||
if want != got {
|
||||
t.Fatalf("isatty(%q): got %v, want %v:", test.name, got, want)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue