From 81c12e363155e8d89ab5ede046b5677dd4e5f4d2 Mon Sep 17 00:00:00 2001 From: Saahil Bhavsar Date: Tue, 23 Jul 2024 00:07:18 +0530 Subject: [PATCH] Updates dependencies Signed-off-by: Saahil Bhavsar --- go.mod | 2 + go.sum | 6 + vendor/github.com/buger/goterm/.gitignore | 2 + vendor/github.com/buger/goterm/LICENSE | 21 ++ vendor/github.com/buger/goterm/README.md | 119 +++++++ vendor/github.com/buger/goterm/box.go | 176 ++++++++++ vendor/github.com/buger/goterm/plot.go | 329 ++++++++++++++++++ vendor/github.com/buger/goterm/table.go | 34 ++ vendor/github.com/buger/goterm/terminal.go | 249 +++++++++++++ .../buger/goterm/terminal_nosysioctl.go | 22 ++ .../buger/goterm/terminal_sysioctl.go | 36 ++ .../buger/goterm/terminal_windows.go | 40 +++ vendor/github.com/pkg/term/.travis.yml | 9 + vendor/github.com/pkg/term/LICENSE | 10 + vendor/github.com/pkg/term/README.md | 201 +++++++++++ vendor/github.com/pkg/term/term.go | 77 ++++ vendor/github.com/pkg/term/term_bsdi.go | 101 ++++++ vendor/github.com/pkg/term/term_bsdu.go | 101 ++++++ vendor/github.com/pkg/term/term_darwin.go | 99 ++++++ vendor/github.com/pkg/term/term_linux.go | 182 ++++++++++ vendor/github.com/pkg/term/term_open_posix.go | 33 ++ vendor/github.com/pkg/term/term_posix.go | 204 +++++++++++ vendor/github.com/pkg/term/term_solaris.go | 165 +++++++++ vendor/github.com/pkg/term/term_windows.go | 114 ++++++ vendor/github.com/pkg/term/termios/doc.go | 4 + vendor/github.com/pkg/term/termios/ioctl.go | 16 + .../pkg/term/termios/ioctl_darwin.go | 10 + .../pkg/term/termios/ioctl_solaris.go | 7 + vendor/github.com/pkg/term/termios/pty.go | 48 +++ vendor/github.com/pkg/term/termios/pty_bsd.go | 37 ++ .../github.com/pkg/term/termios/pty_darwin.go | 36 ++ .../pkg/term/termios/pty_freebsd.go | 38 ++ .../github.com/pkg/term/termios/pty_linux.go | 31 ++ .../github.com/pkg/term/termios/pty_netbsd.go | 31 ++ .../pkg/term/termios/pty_solaris.go | 33 ++ vendor/github.com/pkg/term/termios/termios.go | 45 +++ .../pkg/term/termios/termios_bsd.go | 89 +++++ .../pkg/term/termios/termios_const.go | 13 + .../pkg/term/termios/termios_const_solaris.go | 14 + .../pkg/term/termios/termios_linux.go | 80 +++++ .../pkg/term/termios/termios_solaris.go | 124 +++++++ .../pkg/term/termios/termios_windows.go | 1 + vendor/modules.txt | 7 + 43 files changed, 2996 insertions(+) create mode 100644 vendor/github.com/buger/goterm/.gitignore create mode 100644 vendor/github.com/buger/goterm/LICENSE create mode 100644 vendor/github.com/buger/goterm/README.md create mode 100644 vendor/github.com/buger/goterm/box.go create mode 100644 vendor/github.com/buger/goterm/plot.go create mode 100644 vendor/github.com/buger/goterm/table.go create mode 100644 vendor/github.com/buger/goterm/terminal.go create mode 100644 vendor/github.com/buger/goterm/terminal_nosysioctl.go create mode 100644 vendor/github.com/buger/goterm/terminal_sysioctl.go create mode 100644 vendor/github.com/buger/goterm/terminal_windows.go create mode 100644 vendor/github.com/pkg/term/.travis.yml create mode 100644 vendor/github.com/pkg/term/LICENSE create mode 100644 vendor/github.com/pkg/term/README.md create mode 100644 vendor/github.com/pkg/term/term.go create mode 100644 vendor/github.com/pkg/term/term_bsdi.go create mode 100644 vendor/github.com/pkg/term/term_bsdu.go create mode 100644 vendor/github.com/pkg/term/term_darwin.go create mode 100644 vendor/github.com/pkg/term/term_linux.go create mode 100644 vendor/github.com/pkg/term/term_open_posix.go create mode 100644 vendor/github.com/pkg/term/term_posix.go create mode 100644 vendor/github.com/pkg/term/term_solaris.go create mode 100644 vendor/github.com/pkg/term/term_windows.go create mode 100644 vendor/github.com/pkg/term/termios/doc.go create mode 100644 vendor/github.com/pkg/term/termios/ioctl.go create mode 100644 vendor/github.com/pkg/term/termios/ioctl_darwin.go create mode 100644 vendor/github.com/pkg/term/termios/ioctl_solaris.go create mode 100644 vendor/github.com/pkg/term/termios/pty.go create mode 100644 vendor/github.com/pkg/term/termios/pty_bsd.go create mode 100644 vendor/github.com/pkg/term/termios/pty_darwin.go create mode 100644 vendor/github.com/pkg/term/termios/pty_freebsd.go create mode 100644 vendor/github.com/pkg/term/termios/pty_linux.go create mode 100644 vendor/github.com/pkg/term/termios/pty_netbsd.go create mode 100644 vendor/github.com/pkg/term/termios/pty_solaris.go create mode 100644 vendor/github.com/pkg/term/termios/termios.go create mode 100644 vendor/github.com/pkg/term/termios/termios_bsd.go create mode 100644 vendor/github.com/pkg/term/termios/termios_const.go create mode 100644 vendor/github.com/pkg/term/termios/termios_const_solaris.go create mode 100644 vendor/github.com/pkg/term/termios/termios_linux.go create mode 100644 vendor/github.com/pkg/term/termios/termios_solaris.go create mode 100644 vendor/github.com/pkg/term/termios/termios_windows.go diff --git a/go.mod b/go.mod index 299ce6f..87dd24c 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,10 @@ go 1.22.0 require ( filippo.io/bigmod v0.0.3 github.com/awnumar/memguard v0.22.3 + github.com/buger/goterm v1.0.4 github.com/google/uuid v1.4.0 github.com/lestrrat-go/jwx/v2 v2.0.21 + github.com/pkg/term v1.1.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index 690cea9..b3c5a56 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/awnumar/memcall v0.1.2 h1:7gOfDTL+BJ6nnbtAp9+HQzUFjtP1hEseRQq8eP055QY github.com/awnumar/memcall v0.1.2/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo= github.com/awnumar/memguard v0.22.3 h1:b4sgUXtbUjhrGELPbuC62wU+BsPQy+8lkWed9Z+pj0Y= github.com/awnumar/memguard v0.22.3/go.mod h1:mmGunnffnLHlxE5rRgQc3j+uwPZ27eYb61ccr8Clz2Y= +github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= +github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -51,6 +53,8 @@ github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0= +github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= +github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= 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/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= @@ -97,7 +101,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/buger/goterm/.gitignore b/vendor/github.com/buger/goterm/.gitignore new file mode 100644 index 0000000..986544f --- /dev/null +++ b/vendor/github.com/buger/goterm/.gitignore @@ -0,0 +1,2 @@ +*.swp +.idea \ No newline at end of file diff --git a/vendor/github.com/buger/goterm/LICENSE b/vendor/github.com/buger/goterm/LICENSE new file mode 100644 index 0000000..ac25aeb --- /dev/null +++ b/vendor/github.com/buger/goterm/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Leonid Bugaev + +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. diff --git a/vendor/github.com/buger/goterm/README.md b/vendor/github.com/buger/goterm/README.md new file mode 100644 index 0000000..fc74e21 --- /dev/null +++ b/vendor/github.com/buger/goterm/README.md @@ -0,0 +1,119 @@ +## Description + +This library provides basic building blocks for building advanced console UIs. + +Initially created for [Gor](http://github.com/buger/gor). + +Full API documentation: http://godoc.org/github.com/buger/goterm + +## Basic usage + +Full screen console app, printing current time: + +```go +import ( + tm "github.com/buger/goterm" + "time" +) + +func main() { + tm.Clear() // Clear current screen + + for { + // By moving cursor to top-left position we ensure that console output + // will be overwritten each time, instead of adding new. + tm.MoveCursor(1,1) + + tm.Println("Current Time:", time.Now().Format(time.RFC1123)) + + tm.Flush() // Call it every time at the end of rendering + + time.Sleep(time.Second) + } +} +``` + +This can be seen in [examples/time_example.go](examples/time_example.go). To +run it yourself, go into your `$GOPATH/src/github.com/buger/goterm` directory +and run `go run ./examples/time_example.go` + + +Print red bold message on white background: + +```go +tm.Println(tm.Background(tm.Color(tm.Bold("Important header"), tm.RED), tm.WHITE)) +``` + + +Create box and move it to center of the screen: + +```go +tm.Clear() + +// Create Box with 30% width of current screen, and height of 20 lines +box := tm.NewBox(30|tm.PCT, 20, 0) + +// Add some content to the box +// Note that you can add ANY content, even tables +fmt.Fprint(box, "Some box content") + +// Move Box to approx center of the screen +tm.Print(tm.MoveTo(box.String(), 40|tm.PCT, 40|tm.PCT)) + +tm.Flush() +``` + +This can be found in [examples/box_example.go](examples/box_example.go). + +Draw table: + +```go +// Based on http://golang.org/pkg/text/tabwriter +totals := tm.NewTable(0, 10, 5, ' ', 0) +fmt.Fprintf(totals, "Time\tStarted\tActive\tFinished\n") +fmt.Fprintf(totals, "%s\t%d\t%d\t%d\n", "All", started, started-finished, finished) +tm.Println(totals) +tm.Flush() +``` + +This can be found in [examples/table_example.go](examples/table_example.go). + +## Line charts + +Chart example: + +![screen shot 2013-07-09 at 5 05 37 pm](https://f.cloud.github.com/assets/14009/767676/e3dd35aa-e887-11e2-9cd2-f6451eb26adc.png) + + +```go + import ( + tm "github.com/buger/goterm" + ) + + chart := tm.NewLineChart(100, 20) + + data := new(tm.DataTable) + data.AddColumn("Time") + data.AddColumn("Sin(x)") + data.AddColumn("Cos(x+1)") + + for i := 0.1; i < 10; i += 0.1 { + data.AddRow(i, math.Sin(i), math.Cos(i+1)) + } + + tm.Println(chart.Draw(data)) +``` + +This can be found in [examples/chart_example.go](examples/chart_example.go). + +Drawing 2 separate graphs in different scales. Each graph have its own Y axe. + +```go +chart.Flags = tm.DRAW_INDEPENDENT +``` + +Drawing graph with relative scale (Grapwh draw starting from min value instead of zero) + +```go +chart.Flags = tm.DRAW_RELATIVE +``` diff --git a/vendor/github.com/buger/goterm/box.go b/vendor/github.com/buger/goterm/box.go new file mode 100644 index 0000000..4a119c5 --- /dev/null +++ b/vendor/github.com/buger/goterm/box.go @@ -0,0 +1,176 @@ +package goterm + +import ( + "bytes" + "regexp" + "strings" + _ "unicode/utf8" +) + +const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘" + +// Box allows you to create independent parts of screen, with its own buffer and borders. +// Can be used for creating modal windows +// +// Generates boxes likes this: +// ┌--------┐ +// │hello │ +// │world │ +// │ │ +// └--------┘ +// +type Box struct { + Buf *bytes.Buffer + + Width int + Height int + + // To get even padding: PaddingX ~= PaddingY*4 + PaddingX int + PaddingY int + + // Should contain 6 border pieces separated by spaces + // + // Example border: + // "- │ ┌ ┐ └ ┘" + Border string + + Flags int // Not used now +} + +// Create new Box. +// Width and height can be relative: +// +// // Create box with 50% with of current screen and 10 lines height +// box := tm.NewBox(50|tm.PCT, 10, 0) +// +func NewBox(width, height int, flags int) *Box { + width, height = GetXY(width, height) + + box := new(Box) + box.Buf = new(bytes.Buffer) + box.Width = width + box.Height = height + box.Border = DEFAULT_BORDER + box.PaddingX = 1 + box.PaddingY = 0 + box.Flags = flags + + return box +} + +func (b *Box) Write(p []byte) (int, error) { + return b.Buf.Write(p) +} + +var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`) + +// String renders Box +func (b *Box) String() (out string) { + borders := strings.Split(b.Border, " ") + lines := strings.Split(b.Buf.String(), "\n") + + // Border + padding + prefix := borders[1] + strings.Repeat(" ", b.PaddingX) + suffix := strings.Repeat(" ", b.PaddingX) + borders[1] + + offset := b.PaddingY + 1 // 1 is border width + + // Content width without borders and padding + contentWidth := b.Width - (b.PaddingX+1)*2 + for y := 0; y < b.Height; y++ { + var line string + + switch { + // Draw borders for first line + case y == 0: + line = borders[2] + strings.Repeat(borders[0], b.Width-2) + borders[3] + + // Draw borders for last line + case y == (b.Height - 1): + line = borders[4] + strings.Repeat(borders[0], b.Width-2) + borders[5] + + // Draw top and bottom padding + case y <= b.PaddingY || y >= (b.Height-b.PaddingY): + line = borders[1] + strings.Repeat(" ", b.Width-2) + borders[1] + + // Render content + default: + if len(lines) > y-offset { + line = lines[y-offset] + } else { + line = "" + } + + r := []rune(line) + + lastAnsii := "" + withoutAnsii := []rune{} + withOffset := []rune{} + i := 0 + + for { + if i >= len(r) { + break + } + + if r[i] == 27 { + lastAnsii = "" + withOffset = append(withOffset, r[i]) + lastAnsii += string(r[i]) + i++ + for { + + i++ + if i > len(r) { + break + } + + withOffset = append(withOffset, r[i]) + lastAnsii += string(r[i]) + + if r[i] == 'm' { + i++ + break + } + } + } + + if i >= len(r) { + break + } + + withoutAnsii = append(withoutAnsii, r[i]) + + if len(withoutAnsii) <= contentWidth { + withOffset = append(withOffset, r[i]) + } + + i++ + } + + if len(withoutAnsii) > contentWidth { + // If line is too large limit it + line = string(withOffset) + } else { + // If line is too small enlarge it by adding spaces + line += strings.Repeat(" ", contentWidth-len(withoutAnsii)) + } + + if lastAnsii != "" { + line += RESET + } + + line = prefix + line + suffix + } + + // Don't add newline for last element + if y != b.Height-1 { + line += "\n" + } + + out += line + } + + return out +} diff --git a/vendor/github.com/buger/goterm/plot.go b/vendor/github.com/buger/goterm/plot.go new file mode 100644 index 0000000..504358c --- /dev/null +++ b/vendor/github.com/buger/goterm/plot.go @@ -0,0 +1,329 @@ +package goterm + +import ( + "fmt" + "math" + "strings" + "unicode/utf8" +) + +const ( + AXIS_LEFT = iota + AXIS_RIGHT +) + +const ( + DRAW_INDEPENDENT = 1 << iota + DRAW_RELATIVE +) + +type DataTable struct { + columns []string + + rows [][]float64 +} + +func (d *DataTable) AddColumn(name string) { + d.columns = append(d.columns, name) +} + +func (d *DataTable) AddRow(elms ...float64) { + d.rows = append(d.rows, elms) +} + +type Chart interface { + Draw(data DataTable, flags int) string +} + +type LineChart struct { + Buf []string + chartBuf []string + + data *DataTable + + Width int + Height int + + chartHeight int + chartWidth int + + paddingX int + + paddingY int + + Flags int +} + +func genBuf(size int) []string { + buf := make([]string, size) + + for i := 0; i < size; i++ { + buf[i] = " " + } + + return buf +} + +// Format float +func ff(num interface{}) string { + return fmt.Sprintf("%.1f", num) +} + +func NewLineChart(width, height int) *LineChart { + chart := new(LineChart) + chart.Width = width + chart.Height = height + chart.Buf = genBuf(width * height) + + // axis lines + axies text + chart.paddingY = 2 + + return chart +} + +func (c *LineChart) DrawAxes(maxX, minX, maxY, minY float64, index int) { + side := AXIS_LEFT + + if c.Flags&DRAW_INDEPENDENT != 0 { + if index%2 == 0 { + side = AXIS_RIGHT + } + + c.DrawLine(c.paddingX-1, 1, c.Width-c.paddingX, 1, "-") + } else { + c.DrawLine(c.paddingX-1, 1, c.Width-1, 1, "-") + } + + if side == AXIS_LEFT { + c.DrawLine(c.paddingX-1, 1, c.paddingX-1, c.Height-1, "│") + } else { + c.DrawLine(c.Width-c.paddingX, 1, c.Width-c.paddingX, c.Height-1, "│") + } + + left := 0 + if side == AXIS_RIGHT { + left = c.Width - c.paddingX + 1 + } + + if c.Flags&DRAW_RELATIVE != 0 { + c.writeText(ff(minY), left, 1) + } else { + if minY > 0 { + c.writeText("0", left, 1) + } else { + c.writeText(ff(minY), left, 1) + } + } + + c.writeText(ff(maxY), left, c.Height-1) + + c.writeText(ff(minX), c.paddingX, 0) + + x_col := c.data.columns[0] + c.writeText(c.data.columns[0], c.Width/2-utf8.RuneCountInString(x_col)/2, 1) + + if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 { + col := c.data.columns[index] + + for idx, char := range strings.Split(col, "") { + start_from := c.Height/2 + len(col)/2 - idx + + if side == AXIS_LEFT { + c.writeText(char, c.paddingX-1, start_from) + } else { + c.writeText(char, c.Width-c.paddingX, start_from) + } + } + } + + if c.Flags&DRAW_INDEPENDENT != 0 { + c.writeText(ff(maxX), c.Width-c.paddingX-len(ff(maxX)), 0) + } else { + c.writeText(ff(maxX), c.Width-len(ff(maxX)), 0) + } +} + +func (c *LineChart) writeText(text string, x, y int) { + coord := y*c.Width + x + + for idx, char := range strings.Split(text, "") { + c.Buf[coord+idx] = char + } +} + +func (c *LineChart) Draw(data *DataTable) (out string) { + var scaleY, scaleX float64 + + c.data = data + + if c.Flags&DRAW_INDEPENDENT != 0 && len(data.columns) > 3 { + fmt.Println("Error: Can't use DRAW_INDEPENDENT for more then 2 graphs") + return "" + } + + charts := len(data.columns) - 1 + + prevPoint := [2]int{-1, -1} + + maxX, minX, maxY, minY := getBoundaryValues(data, -1) + + c.paddingX = int(math.Max(float64(len(ff(minY))), float64(len(ff(maxY))))) + 1 + + c.chartHeight = c.Height - c.paddingY + + if c.Flags&DRAW_INDEPENDENT != 0 { + c.chartWidth = c.Width - 2*c.paddingX + } else { + c.chartWidth = c.Width - c.paddingX - 1 + } + + scaleX = float64(c.chartWidth) / (maxX - minX) + + if c.Flags&DRAW_RELATIVE != 0 || minY < 0 { + scaleY = float64(c.chartHeight) / (maxY - minY) + } else { + scaleY = float64(c.chartHeight) / maxY + } + + for i := 1; i < charts+1; i++ { + if c.Flags&DRAW_INDEPENDENT != 0 { + maxX, minX, maxY, minY = getBoundaryValues(data, i) + + scaleX = float64(c.chartWidth-1) / (maxX - minX) + scaleY = float64(c.chartHeight) / maxY + + if c.Flags&DRAW_RELATIVE != 0 || minY < 0 { + scaleY = float64(c.chartHeight) / (maxY - minY) + } + } + + symbol := Color("•", i) + + c_data := getChartData(data, i) + + for _, point := range c_data { + x := int((point[0]-minX)*scaleX) + c.paddingX + y := int((point[1])*scaleY) + c.paddingY + + if c.Flags&DRAW_RELATIVE != 0 || minY < 0 { + y = int((point[1]-minY)*scaleY) + c.paddingY + } + + if prevPoint[0] == -1 { + prevPoint[0] = x + prevPoint[1] = y + } + + if prevPoint[0] <= x { + c.DrawLine(prevPoint[0], prevPoint[1], x, y, symbol) + } + + prevPoint[0] = x + prevPoint[1] = y + } + + c.DrawAxes(maxX, minX, maxY, minY, i) + } + + for row := c.Height - 1; row >= 0; row-- { + out += strings.Join(c.Buf[row*c.Width:(row+1)*c.Width], "") + "\n" + } + + return +} + +func (c *LineChart) DrawLine(x0, y0, x1, y1 int, symbol string) { + drawLine(x0, y0, x1, y1, func(x, y int) { + coord := y*c.Width + x + + if coord > 0 && coord < len(c.Buf) { + c.Buf[coord] = symbol + } + }) +} + +func getBoundaryValues(data *DataTable, index int) (maxX, minX, maxY, minY float64) { + maxX = math.Inf(-1) + minX = math.Inf(1) + maxY = math.Inf(-1) + minY = math.Inf(1) + + for _, r := range data.rows { + maxX = math.Max(maxX, r[0]) + minX = math.Min(minX, r[0]) + + for idx, c := range r { + if idx > 0 { + if index == -1 || index == idx { + maxY = math.Max(maxY, c) + minY = math.Min(minY, c) + } + } + } + } + + if maxY > 0 { + maxY = maxY * 1.1 + } else { + maxY = maxY * 0.9 + } + + if minY > 0 { + minY = minY * 0.9 + } else { + minY = minY * 1.1 + } + + return +} + +// DataTable can contain data for multiple graphs, we need to extract only 1 +func getChartData(data *DataTable, index int) (out [][]float64) { + for _, r := range data.rows { + out = append(out, []float64{r[0], r[index]}) + } + + return +} + +// Algorithm for drawing line between two points +// +// http://en.wikipedia.org/wiki/Bresenham's_line_algorithm +func drawLine(x0, y0, x1, y1 int, plot func(int, int)) { + dx := x1 - x0 + if dx < 0 { + dx = -dx + } + dy := y1 - y0 + if dy < 0 { + dy = -dy + } + var sx, sy int + if x0 < x1 { + sx = 1 + } else { + sx = -1 + } + if y0 < y1 { + sy = 1 + } else { + sy = -1 + } + err := dx - dy + + for { + plot(x0, y0) + if x0 == x1 && y0 == y1 { + break + } + e2 := 2 * err + if e2 > -dy { + err -= dy + x0 += sx + } + if e2 < dx { + err += dx + y0 += sy + } + } +} diff --git a/vendor/github.com/buger/goterm/table.go b/vendor/github.com/buger/goterm/table.go new file mode 100644 index 0000000..d8dae55 --- /dev/null +++ b/vendor/github.com/buger/goterm/table.go @@ -0,0 +1,34 @@ +package goterm + +import ( + "bytes" + "text/tabwriter" +) + +// Tabwriter with own buffer: +// +// totals := tm.NewTable(0, 10, 5, ' ', 0) +// fmt.Fprintf(totals, "Time\tStarted\tActive\tFinished\n") +// fmt.Fprintf(totals, "%s\t%d\t%d\t%d\n", "All", started, started-finished, finished) +// tm.Println(totals) +// +// Based on http://golang.org/pkg/text/tabwriter +type Table struct { + tabwriter.Writer + + Buf *bytes.Buffer +} + +// Same as here http://golang.org/pkg/text/tabwriter/#Writer.Init +func NewTable(minwidth, tabwidth, padding int, padchar byte, flags uint) *Table { + tbl := new(Table) + tbl.Buf = new(bytes.Buffer) + tbl.Init(tbl.Buf, minwidth, tabwidth, padding, padchar, flags) + + return tbl +} + +func (t *Table) String() string { + t.Flush() + return t.Buf.String() +} diff --git a/vendor/github.com/buger/goterm/terminal.go b/vendor/github.com/buger/goterm/terminal.go new file mode 100644 index 0000000..d1e8208 --- /dev/null +++ b/vendor/github.com/buger/goterm/terminal.go @@ -0,0 +1,249 @@ +// Provides basic bulding blocks for advanced console UI +// +// Coordinate system: +// +// 1/1---X----> +// | +// Y +// | +// v +// +// Documentation for ANSI codes: http://en.wikipedia.org/wiki/ANSI_escape_code#Colors +// +// Inspired by: http://www.darkcoding.net/software/pretty-command-line-console-output-on-unix-in-python-and-go-lang/ +package goterm + +import ( + "bufio" + "bytes" + "fmt" + "os" + "strings" +) + +// Reset all custom styles +const RESET = "\033[0m" + +// Reset to default color +const RESET_COLOR = "\033[32m" + +// Return cursor to start of line and clean it +const RESET_LINE = "\r\033[K" + +// List of possible colors +const ( + BLACK = iota + RED + GREEN + YELLOW + BLUE + MAGENTA + CYAN + WHITE +) + +var Output *bufio.Writer = bufio.NewWriter(os.Stdout) + +func getColor(code int) string { + return fmt.Sprintf("\033[3%dm", code) +} + +func getBgColor(code int) string { + return fmt.Sprintf("\033[4%dm", code) +} + +// Set percent flag: num | PCT +// +// Check percent flag: num & PCT +// +// Reset percent flag: num & 0xFF +const shift = uint(^uint(0)>>63) << 4 +const PCT = 0x8000 << shift + +type winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +// Global screen buffer +// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead. +var Screen *bytes.Buffer = new(bytes.Buffer) + +// GetXY gets relative or absolute coordinates +// To get relative, set PCT flag to number: +// +// // Get 10% of total width to `x` and 20 to y +// x, y = tm.GetXY(10|tm.PCT, 20) +// +func GetXY(x int, y int) (int, int) { + if y == -1 { + y = CurrentHeight() + 1 + } + + if x&PCT != 0 { + x = int((x & 0xFF) * Width() / 100) + } + + if y&PCT != 0 { + y = int((y & 0xFF) * Height() / 100) + } + + return x, y +} + +type sf func(int, string) string + +// Apply given transformation func for each line in string +func applyTransform(str string, transform sf) (out string) { + out = "" + + for idx, line := range strings.Split(str, "\n") { + out += transform(idx, line) + } + + return +} + +// Clear screen +func Clear() { + Output.WriteString("\033[2J") +} + +// Move cursor to given position +func MoveCursor(x int, y int) { + fmt.Fprintf(Screen, "\033[%d;%dH", y, x) +} + +// Move cursor up relative the current position +func MoveCursorUp(bias int) { + fmt.Fprintf(Screen, "\033[%dA", bias) +} + +// Move cursor down relative the current position +func MoveCursorDown(bias int) { + fmt.Fprintf(Screen, "\033[%dB", bias) +} + +// Move cursor forward relative the current position +func MoveCursorForward(bias int) { + fmt.Fprintf(Screen, "\033[%dC", bias) +} + +// Move cursor backward relative the current position +func MoveCursorBackward(bias int) { + fmt.Fprintf(Screen, "\033[%dD", bias) +} + +// Move string to possition +func MoveTo(str string, x int, y int) (out string) { + x, y = GetXY(x, y) + + return applyTransform(str, func(idx int, line string) string { + return fmt.Sprintf("\033[%d;%dH%s", y+idx, x, line) + }) +} + +// ResetLine returns carrier to start of line +func ResetLine(str string) (out string) { + return applyTransform(str, func(idx int, line string) string { + return fmt.Sprintf("%s%s", RESET_LINE, line) + }) +} + +// Make bold +func Bold(str string) string { + return applyTransform(str, func(idx int, line string) string { + return fmt.Sprintf("\033[1m%s\033[0m", line) + }) +} + +// Apply given color to string: +// +// tm.Color("RED STRING", tm.RED) +// +func Color(str string, color int) string { + return applyTransform(str, func(idx int, line string) string { + return fmt.Sprintf("%s%s%s", getColor(color), line, RESET) + }) +} + +func Highlight(str, substr string, color int) string { + hiSubstr := Color(substr, color) + return strings.Replace(str, substr, hiSubstr, -1) +} + +func HighlightRegion(str string, from, to, color int) string { + return str[:from] + Color(str[from:to], color) + str[to:] +} + +// Change background color of string: +// +// tm.Background("string", tm.RED) +// +func Background(str string, color int) string { + return applyTransform(str, func(idx int, line string) string { + return fmt.Sprintf("%s%s%s", getBgColor(color), line, RESET) + }) +} + +// Width gets console width +func Width() int { + ws, err := getWinsize() + + if err != nil { + return -1 + } + + return int(ws.Col) +} + +// CurrentHeight gets current height. Line count in Screen buffer. +func CurrentHeight() int { + return strings.Count(Screen.String(), "\n") +} + +// Flush buffer and ensure that it will not overflow screen +func Flush() { + for idx, str := range strings.SplitAfter(Screen.String(), "\n") { + if idx > Height() { + return + } + + Output.WriteString(str) + } + + Output.Flush() + Screen.Reset() +} + +func Print(a ...interface{}) (n int, err error) { + return fmt.Fprint(Screen, a...) +} + +func Println(a ...interface{}) (n int, err error) { + return fmt.Fprintln(Screen, a...) +} + +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(Screen, format, a...) +} + +func Context(data string, idx, max int) string { + var start, end int + + if len(data[:idx]) < (max / 2) { + start = 0 + } else { + start = idx - max/2 + } + + if len(data)-idx < (max / 2) { + end = len(data) - 1 + } else { + end = idx + max/2 + } + + return data[start:end] +} diff --git a/vendor/github.com/buger/goterm/terminal_nosysioctl.go b/vendor/github.com/buger/goterm/terminal_nosysioctl.go new file mode 100644 index 0000000..f4f4d5e --- /dev/null +++ b/vendor/github.com/buger/goterm/terminal_nosysioctl.go @@ -0,0 +1,22 @@ +//go:build plan9 || solaris +// +build plan9 solaris + +package goterm + +func getWinsize() (*winsize, error) { + ws := new(winsize) + + ws.Col = 80 + ws.Row = 24 + + return ws, nil +} + +// Height gets console height +func Height() int { + ws, err := getWinsize() + if err != nil { + return -1 + } + return int(ws.Row) +} diff --git a/vendor/github.com/buger/goterm/terminal_sysioctl.go b/vendor/github.com/buger/goterm/terminal_sysioctl.go new file mode 100644 index 0000000..8b48b40 --- /dev/null +++ b/vendor/github.com/buger/goterm/terminal_sysioctl.go @@ -0,0 +1,36 @@ +//go:build !windows && !plan9 && !solaris +// +build !windows,!plan9,!solaris + +package goterm + +import ( + "errors" + "math" + "os" + + "golang.org/x/sys/unix" +) + +func getWinsize() (*unix.Winsize, error) { + + ws, err := unix.IoctlGetWinsize(int(os.Stdout.Fd()), unix.TIOCGWINSZ) + if err != nil { + return nil, os.NewSyscallError("GetWinsize", err) + } + + return ws, nil +} + +// Height gets console height +func Height() int { + ws, err := getWinsize() + if err != nil { + // returns math.MinInt32 if we could not retrieve the height of console window, + // like VSCode debugging console + if errors.Is(err, unix.EOPNOTSUPP) { + return math.MinInt32 + } + return -1 + } + return int(ws.Row) +} diff --git a/vendor/github.com/buger/goterm/terminal_windows.go b/vendor/github.com/buger/goterm/terminal_windows.go new file mode 100644 index 0000000..e8236b6 --- /dev/null +++ b/vendor/github.com/buger/goterm/terminal_windows.go @@ -0,0 +1,40 @@ +//go:build windows +// +build windows + +package goterm + +import ( + "errors" + "math" + "os" + + "golang.org/x/sys/windows" +) + +func getWinsize() (*winsize, error) { + ws := new(winsize) + fd := os.Stdout.Fd() + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return nil, err + } + + ws.Col = uint16(info.Window.Right - info.Window.Left + 1) + ws.Row = uint16(info.Window.Bottom - info.Window.Top + 1) + + return ws, nil +} + +// Height gets console height +func Height() int { + ws, err := getWinsize() + if err != nil { + // returns math.MinInt32 if we could not retrieve the height of console window, + // like VSCode debugging console + if errors.Is(err, windows.WSAEOPNOTSUPP) { + return math.MinInt32 + } + return -1 + } + return int(ws.Row) +} diff --git a/vendor/github.com/pkg/term/.travis.yml b/vendor/github.com/pkg/term/.travis.yml new file mode 100644 index 0000000..a4dce2b --- /dev/null +++ b/vendor/github.com/pkg/term/.travis.yml @@ -0,0 +1,9 @@ +language: go +go_import_path: github.com/pkg/term +go: + - 1.13.x + - 1.14.x + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pkg/term/LICENSE b/vendor/github.com/pkg/term/LICENSE new file mode 100644 index 0000000..8b9d157 --- /dev/null +++ b/vendor/github.com/pkg/term/LICENSE @@ -0,0 +1,10 @@ +Copyright (c) 2014, David Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +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. diff --git a/vendor/github.com/pkg/term/README.md b/vendor/github.com/pkg/term/README.md new file mode 100644 index 0000000..a278804 --- /dev/null +++ b/vendor/github.com/pkg/term/README.md @@ -0,0 +1,201 @@ + +# term + import "github.com/pkg/term" + +Package term manages POSIX terminals. As POSIX terminals are connected to, +or emulate, a UART, this package also provides control over the various +UART and serial line parameters. + + + + + + +## func CBreakMode +``` go +func CBreakMode(t *Term) error +``` +CBreakMode places the terminal into cbreak mode. + + +## func RawMode +``` go +func RawMode(t *Term) error +``` +RawMode places the terminal into raw mode. + + +## func Speed +``` go +func Speed(baud int) func(*Term) error +``` +Speed sets the baud rate option for the terminal. + + + +## type Term +``` go +type Term struct { + // contains filtered or unexported fields +} +``` +Term represents an asynchronous communications port. + + + + + + + + + +### func Open +``` go +func Open(name string, options ...func(*Term) error) (*Term, error) +``` +Open opens an asynchronous communications port. + + + + +### func (\*Term) Available +``` go +func (t *Term) Available() (int, error) +``` +Available returns how many bytes are unused in the buffer. + + + +### func (\*Term) Buffered +``` go +func (t *Term) Buffered() (int, error) +``` +Buffered returns the number of bytes that have been written into the current buffer. + + + +### func (\*Term) Close +``` go +func (t *Term) Close() error +``` +Close closes the device and releases any associated resources. + + + +### func (\*Term) DTR +``` go +func (t *Term) DTR() (bool, error) +``` +DTR returns the state of the DTR (data terminal ready) signal. + + + +### func (\*Term) Flush +``` go +func (t *Term) Flush() error +``` +Flush flushes both data received but not read, and data written but not transmitted. + + + +### func (\*Term) RTS +``` go +func (t *Term) RTS() (bool, error) +``` +RTS returns the state of the RTS (data terminal ready) signal. + + + +### func (\*Term) Read +``` go +func (t *Term) Read(b []byte) (int, error) +``` +Read reads up to len(b) bytes from the terminal. It returns the number of +bytes read and an error, if any. EOF is signaled by a zero count with +err set to io.EOF. + + + +### func (\*Term) Restore +``` go +func (t *Term) Restore() error +``` +Restore restores the state of the terminal captured at the point that +the terminal was originally opened. + + + +### func (\*Term) SendBreak +``` go +func (t *Term) SendBreak() error +``` +SendBreak sends a break signal. + + + +### func (\*Term) SetCbreak +``` go +func (t *Term) SetCbreak() error +``` +SetCbreak sets cbreak mode. + + + +### func (\*Term) SetDTR +``` go +func (t *Term) SetDTR(v bool) error +``` +SetDTR sets the DTR (data terminal ready) signal. + + + +### func (\*Term) SetOption +``` go +func (t *Term) SetOption(options ...func(*Term) error) error +``` +SetOption takes one or more option function and applies them in order to Term. + + + +### func (\*Term) SetRTS +``` go +func (t *Term) SetRTS(v bool) error +``` +SetRTS sets the RTS (data terminal ready) signal. + + + +### func (\*Term) SetRaw +``` go +func (t *Term) SetRaw() error +``` +SetRaw sets raw mode. + + + +### func (\*Term) SetSpeed +``` go +func (t *Term) SetSpeed(baud int) error +``` +SetSpeed sets the receive and transmit baud rates. + + + +### func (\*Term) Write +``` go +func (t *Term) Write(b []byte) (int, error) +``` +Write writes len(b) bytes to the terminal. It returns the number of bytes +written and an error, if any. Write returns a non-nil error when n != +len(b). + + + + + + + + + +- - - +Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) \ No newline at end of file diff --git a/vendor/github.com/pkg/term/term.go b/vendor/github.com/pkg/term/term.go new file mode 100644 index 0000000..e0aacb3 --- /dev/null +++ b/vendor/github.com/pkg/term/term.go @@ -0,0 +1,77 @@ +// +build !windows + +// Package term manages POSIX terminals. As POSIX terminals are connected to, +// or emulate, a UART, this package also provides control over the various +// UART and serial line parameters. +package term + +import ( + "errors" + "io" + "os" + + "github.com/pkg/term/termios" + "golang.org/x/sys/unix" +) + +const ( + NONE = iota // flow control off + XONXOFF // software flow control + HARDWARE // hardware flow control +) + +var errNotSupported = errors.New("not supported") + +// Read reads up to len(b) bytes from the terminal. It returns the number of +// bytes read and an error, if any. EOF is signaled by a zero count with +// err set to io.EOF. +func (t *Term) Read(b []byte) (int, error) { + n, e := unix.Read(t.fd, b) + if n < 0 { + n = 0 + } + if n == 0 && len(b) > 0 && e == nil { + return 0, io.EOF + } + if e != nil { + return n, &os.PathError{"read", t.name, e} + } + return n, nil +} + +// SetOption takes one or more option function and applies them in order to Term. +func (t *Term) SetOption(options ...func(*Term) error) error { + for _, opt := range options { + if err := opt(t); err != nil { + return err + } + } + return nil +} + +// Write writes len(b) bytes to the terminal. It returns the number of bytes +// written and an error, if any. Write returns a non-nil error when n != +// len(b). +func (t *Term) Write(b []byte) (int, error) { + n, e := unix.Write(t.fd, b) + if n < 0 { + n = 0 + } + if n != len(b) { + return n, io.ErrShortWrite + } + if e != nil { + return n, &os.PathError{"write", t.name, e} + } + return n, nil +} + +// Available returns how many bytes are unused in the buffer. +func (t *Term) Available() (int, error) { + return termios.Tiocinq(uintptr(t.fd)) +} + +// Buffered returns the number of bytes that have been written into the current buffer. +func (t *Term) Buffered() (int, error) { + return termios.Tiocoutq(uintptr(t.fd)) +} diff --git a/vendor/github.com/pkg/term/term_bsdi.go b/vendor/github.com/pkg/term/term_bsdi.go new file mode 100644 index 0000000..1b39d09 --- /dev/null +++ b/vendor/github.com/pkg/term/term_bsdi.go @@ -0,0 +1,101 @@ +// +build netbsd openbsd + +package term + +import "golang.org/x/sys/unix" + +type attr unix.Termios + +func (a *attr) getSpeed() (int, error) { + // We generally only care about ospeed, since that's what would + // be used for padding characters, for example. + + switch a.Ospeed { + case syscall.B50: + return 50, nil + case syscall.B75: + return 75, nil + case syscall.B110: + return 110, nil + case syscall.B134: + return 134, nil + case syscall.B150: + return 150, nil + case syscall.B200: + return 200, nil + case syscall.B300: + return 300, nil + case syscall.B600: + return 600, nil + case syscall.B1200: + return 1200, nil + case syscall.B1800: + return 1800, nil + case syscall.B2400: + return 2400, nil + case syscall.B4800: + return 4800, nil + case syscall.B9600: + return 9600, nil + case syscall.B19200: + return 19200, nil + case syscall.B38400: + return 38400, nil + case syscall.B57600: + return 57600, nil + case syscall.B115200: + return 115200, nil + case syscall.B230400: + return 230400, nil + default: + return 0, syscall.EINVAL + } +} + +func (a *attr) setSpeed(baud int) error { + var rate int32 + switch baud { + case 50: + rate = unix.B50 + case 75: + rate = unix.B75 + case 110: + rate = unix.B110 + case 134: + rate = unix.B134 + case 150: + rate = unix.B150 + case 200: + rate = unix.B200 + case 300: + rate = unix.B300 + case 600: + rate = unix.B600 + case 1200: + rate = unix.B1200 + case 1800: + rate = unix.B1800 + case 2400: + rate = unix.B2400 + case 4800: + rate = unix.B4800 + case 9600: + rate = unix.B9600 + case 19200: + rate = unix.B19200 + case 38400: + rate = unix.B38400 + case 57600: + rate = unix.B57600 + case 115200: + rate = unix.B115200 + case 230400: + rate = unix.B230400 + default: + return unix.EINVAL + } + (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | uint32(rate) + (*unix.Termios)(a).Ispeed = rate + (*unix.Termios)(a).Ospeed = rate + return nil +} diff --git a/vendor/github.com/pkg/term/term_bsdu.go b/vendor/github.com/pkg/term/term_bsdu.go new file mode 100644 index 0000000..7b9f848 --- /dev/null +++ b/vendor/github.com/pkg/term/term_bsdu.go @@ -0,0 +1,101 @@ +// +build dragonfly freebsd + +package term + +import "golang.org/x/sys/unix" + +type attr unix.Termios + +func (a *attr) getSpeed() (int, error) { + // We generally only care about ospeed, since that's what would + // be used for padding characters, for example. + + switch a.Ospeed { + case syscall.B50: + return 50, nil + case syscall.B75: + return 75, nil + case syscall.B110: + return 110, nil + case syscall.B134: + return 134, nil + case syscall.B150: + return 150, nil + case syscall.B200: + return 200, nil + case syscall.B300: + return 300, nil + case syscall.B600: + return 600, nil + case syscall.B1200: + return 1200, nil + case syscall.B1800: + return 1800, nil + case syscall.B2400: + return 2400, nil + case syscall.B4800: + return 4800, nil + case syscall.B9600: + return 9600, nil + case syscall.B19200: + return 19200, nil + case syscall.B38400: + return 38400, nil + case syscall.B57600: + return 57600, nil + case syscall.B115200: + return 115200, nil + case syscall.B230400: + return 230400, nil + default: + return 0, syscall.EINVAL + } +} + +func (a *attr) setSpeed(baud int) error { + var rate uint32 + switch baud { + case 50: + rate = unix.B50 + case 75: + rate = unix.B75 + case 110: + rate = unix.B110 + case 134: + rate = unix.B134 + case 150: + rate = unix.B150 + case 200: + rate = unix.B200 + case 300: + rate = unix.B300 + case 600: + rate = unix.B600 + case 1200: + rate = unix.B1200 + case 1800: + rate = unix.B1800 + case 2400: + rate = unix.B2400 + case 4800: + rate = unix.B4800 + case 9600: + rate = unix.B9600 + case 19200: + rate = unix.B19200 + case 38400: + rate = unix.B38400 + case 57600: + rate = unix.B57600 + case 115200: + rate = unix.B115200 + case 230400: + rate = unix.B230400 + default: + return unix.EINVAL + } + (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate + (*unix.Termios)(a).Ispeed = rate + (*unix.Termios)(a).Ospeed = rate + return nil +} diff --git a/vendor/github.com/pkg/term/term_darwin.go b/vendor/github.com/pkg/term/term_darwin.go new file mode 100644 index 0000000..2e0568c --- /dev/null +++ b/vendor/github.com/pkg/term/term_darwin.go @@ -0,0 +1,99 @@ +package term + +import "golang.org/x/sys/unix" + +type attr unix.Termios + +func (a *attr) getSpeed() (int, error) { + // We generally only care about ospeed, since that's what would + // be used for padding characters, for example. + + switch a.Ospeed { + case unix.B50: + return 50, nil + case unix.B75: + return 75, nil + case unix.B110: + return 110, nil + case unix.B134: + return 134, nil + case unix.B150: + return 150, nil + case unix.B200: + return 200, nil + case unix.B300: + return 300, nil + case unix.B600: + return 600, nil + case unix.B1200: + return 1200, nil + case unix.B1800: + return 1800, nil + case unix.B2400: + return 2400, nil + case unix.B4800: + return 4800, nil + case unix.B9600: + return 9600, nil + case unix.B19200: + return 19200, nil + case unix.B38400: + return 38400, nil + case unix.B57600: + return 57600, nil + case unix.B115200: + return 115200, nil + case unix.B230400: + return 230400, nil + default: + return 0, unix.EINVAL + } +} + +func (a *attr) setSpeed(baud int) error { + var rate uint64 + switch baud { + case 50: + rate = unix.B50 + case 75: + rate = unix.B75 + case 110: + rate = unix.B110 + case 134: + rate = unix.B134 + case 150: + rate = unix.B150 + case 200: + rate = unix.B200 + case 300: + rate = unix.B300 + case 600: + rate = unix.B600 + case 1200: + rate = unix.B1200 + case 1800: + rate = unix.B1800 + case 2400: + rate = unix.B2400 + case 4800: + rate = unix.B4800 + case 9600: + rate = unix.B9600 + case 19200: + rate = unix.B19200 + case 38400: + rate = unix.B38400 + case 57600: + rate = unix.B57600 + case 115200: + rate = unix.B115200 + case 230400: + rate = unix.B230400 + default: + return unix.EINVAL + } + (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate + (*unix.Termios)(a).Ispeed = rate + (*unix.Termios)(a).Ospeed = rate + return nil +} diff --git a/vendor/github.com/pkg/term/term_linux.go b/vendor/github.com/pkg/term/term_linux.go new file mode 100644 index 0000000..d85b211 --- /dev/null +++ b/vendor/github.com/pkg/term/term_linux.go @@ -0,0 +1,182 @@ +package term + +import "golang.org/x/sys/unix" + +type attr unix.Termios + +const ( + // CBaudMask is the logical of CBAUD and CBAUDEX, except + // that those values were not exposed via the syscall + // package. Many of these values will be redundant, but + // this long definition ensures we are portable if some + // architecture defines different values for them (unlikely). + CBaudMask = unix.B50 | + unix.B75 | + unix.B110 | + unix.B134 | + unix.B150 | + unix.B200 | + unix.B300 | + unix.B600 | + unix.B1200 | + unix.B1800 | + unix.B2400 | + unix.B4800 | + unix.B9600 | + unix.B19200 | + unix.B38400 | + unix.B57600 | + unix.B115200 | + unix.B230400 | + unix.B460800 | + unix.B500000 | + unix.B576000 | + unix.B921600 | + unix.B1000000 | + unix.B1152000 | + unix.B1500000 | + unix.B2000000 | + unix.B2500000 | + unix.B3000000 | + unix.B3500000 | + unix.B4000000 +) + +func (a *attr) getSpeed() (int, error) { + switch a.Cflag & CBaudMask { + case unix.B50: + return 50, nil + case unix.B75: + return 75, nil + case unix.B110: + return 110, nil + case unix.B134: + return 134, nil + case unix.B150: + return 150, nil + case unix.B200: + return 200, nil + case unix.B300: + return 300, nil + case unix.B600: + return 600, nil + case unix.B1200: + return 1200, nil + case unix.B1800: + return 1800, nil + case unix.B2400: + return 2400, nil + case unix.B4800: + return 4800, nil + case unix.B9600: + return 9600, nil + case unix.B19200: + return 19200, nil + case unix.B38400: + return 38400, nil + case unix.B57600: + return 57600, nil + case unix.B115200: + return 115200, nil + case unix.B230400: + return 230400, nil + case unix.B460800: + return 460800, nil + case unix.B500000: + return 500000, nil + case unix.B576000: + return 576000, nil + case unix.B921600: + return 921600, nil + case unix.B1000000: + return 1000000, nil + case unix.B1152000: + return 1152000, nil + case unix.B1500000: + return 1500000, nil + case unix.B2000000: + return 2000000, nil + case unix.B2500000: + return 2500000, nil + case unix.B3000000: + return 3000000, nil + case unix.B3500000: + return 3500000, nil + case unix.B4000000: + return 4000000, nil + default: + return 0, unix.EINVAL + } +} + +func (a *attr) setSpeed(baud int) error { + var rate uint32 + switch baud { + case 50: + rate = unix.B50 + case 75: + rate = unix.B75 + case 110: + rate = unix.B110 + case 134: + rate = unix.B134 + case 150: + rate = unix.B150 + case 200: + rate = unix.B200 + case 300: + rate = unix.B300 + case 600: + rate = unix.B600 + case 1200: + rate = unix.B1200 + case 1800: + rate = unix.B1800 + case 2400: + rate = unix.B2400 + case 4800: + rate = unix.B4800 + case 9600: + rate = unix.B9600 + case 19200: + rate = unix.B19200 + case 38400: + rate = unix.B38400 + case 57600: + rate = unix.B57600 + case 115200: + rate = unix.B115200 + case 230400: + rate = unix.B230400 + case 460800: + rate = unix.B460800 + case 500000: + rate = unix.B500000 + case 576000: + rate = unix.B576000 + case 921600: + rate = unix.B921600 + case 1000000: + rate = unix.B1000000 + case 1152000: + rate = unix.B1152000 + case 1500000: + rate = unix.B1500000 + case 2000000: + rate = unix.B2000000 + case 2500000: + rate = unix.B2500000 + case 3000000: + rate = unix.B3000000 + case 3500000: + rate = unix.B3500000 + case 4000000: + rate = unix.B4000000 + default: + return unix.EINVAL + } + (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate + (*unix.Termios)(a).Ispeed = rate + (*unix.Termios)(a).Ospeed = rate + return nil +} diff --git a/vendor/github.com/pkg/term/term_open_posix.go b/vendor/github.com/pkg/term/term_open_posix.go new file mode 100644 index 0000000..5919a3d --- /dev/null +++ b/vendor/github.com/pkg/term/term_open_posix.go @@ -0,0 +1,33 @@ +// +build !windows,!solaris + +package term + +import ( + "os" + + "github.com/pkg/term/termios" + "golang.org/x/sys/unix" +) + +// Open opens an asynchronous communications port. +func Open(name string, options ...func(*Term) error) (*Term, error) { + fd, e := unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666) + if e != nil { + return nil, &os.PathError{"open", name, e} + } + + t := Term{name: name, fd: fd} + if err := termios.Tcgetattr(uintptr(t.fd), &t.orig); err != nil { + return nil, err + } + if err := t.SetOption(options...); err != nil { + return nil, err + } + return &t, unix.SetNonblock(t.fd, false) +} + +// Restore restores the state of the terminal captured at the point that +// the terminal was originally opened. +func (t *Term) Restore() error { + return termios.Tcsetattr(uintptr(t.fd), termios.TCIOFLUSH, &t.orig) +} diff --git a/vendor/github.com/pkg/term/term_posix.go b/vendor/github.com/pkg/term/term_posix.go new file mode 100644 index 0000000..d577779 --- /dev/null +++ b/vendor/github.com/pkg/term/term_posix.go @@ -0,0 +1,204 @@ +// +build !windows + +package term + +import ( + "time" + + "github.com/pkg/term/termios" + "golang.org/x/sys/unix" +) + +// Term represents an asynchronous communications port. +type Term struct { + name string + fd int + orig unix.Termios // original state of the terminal, see Open and Restore +} + +// SetCbreak sets cbreak mode. +func (t *Term) SetCbreak() error { + return t.SetOption(CBreakMode) +} + +// CBreakMode places the terminal into cbreak mode. +func CBreakMode(t *Term) error { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return err + } + termios.Cfmakecbreak((*unix.Termios)(&a)) + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) +} + +// SetRaw sets raw mode. +func (t *Term) SetRaw() error { + return t.SetOption(RawMode) +} + +// RawMode places the terminal into raw mode. +func RawMode(t *Term) error { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return err + } + termios.Cfmakeraw((*unix.Termios)(&a)) + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) +} + +// Speed sets the baud rate option for the terminal. +func Speed(baud int) func(*Term) error { + return func(t *Term) error { + return t.setSpeed(baud) + } +} + +// SetSpeed sets the receive and transmit baud rates. +func (t *Term) SetSpeed(baud int) error { + return t.SetOption(Speed(baud)) +} + +func (t *Term) setSpeed(baud int) error { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return err + } + a.setSpeed(baud) + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) +} + +// GetSpeed gets the current output baud rate. +func (t *Term) GetSpeed() (int, error) { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return 0, err + } + return a.getSpeed() +} + +func clamp(v, lo, hi int64) int64 { + if v < lo { + return lo + } + if v > hi { + return hi + } + return v +} + +// timeoutVals converts d into values suitable for termios VMIN and VTIME ctrl chars +func timeoutVals(d time.Duration) (uint8, uint8) { + if d > 0 { + // VTIME is expressed in terms of deciseconds + vtimeDeci := d.Nanoseconds() / 1e6 / 100 + // ensure valid range + vtime := uint8(clamp(vtimeDeci, 1, 0xff)) + return 0, vtime + } + // block indefinitely until we receive at least 1 byte + return 1, 0 +} + +// ReadTimeout sets the read timeout option for the terminal. +func ReadTimeout(d time.Duration) func(*Term) error { + return func(t *Term) error { + return t.setReadTimeout(d) + } +} + +// SetReadTimeout sets the read timeout. +// A zero value for d means read operations will not time out. +func (t *Term) SetReadTimeout(d time.Duration) error { + return t.SetOption(ReadTimeout(d)) +} + +func (t *Term) setReadTimeout(d time.Duration) error { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return err + } + a.Cc[unix.VMIN], a.Cc[unix.VTIME] = timeoutVals(d) + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) +} + +// FlowControl sets the flow control option for the terminal. +func FlowControl(kind int) func(*Term) error { + return func(t *Term) error { + return t.setFlowControl(kind) + } +} + +// SetFlowControl sets whether hardware flow control is enabled. +func (t *Term) SetFlowControl(kind int) error { + return t.SetOption(FlowControl(kind)) +} + +func (t *Term) setFlowControl(kind int) error { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { + return err + } + switch kind { + case NONE: + a.Iflag &^= termios.IXON | termios.IXOFF | termios.IXANY + a.Cflag &^= termios.CRTSCTS + + case XONXOFF: + a.Cflag &^= termios.CRTSCTS + a.Iflag |= termios.IXON | termios.IXOFF | termios.IXANY + + case HARDWARE: + a.Iflag &^= termios.IXON | termios.IXOFF | termios.IXANY + a.Cflag |= termios.CRTSCTS + } + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) +} + +// Flush flushes both data received but not read, and data written but not transmitted. +func (t *Term) Flush() error { + return termios.Tcflush(uintptr(t.fd), termios.TCIOFLUSH) +} + +// SendBreak sends a break signal. +func (t *Term) SendBreak() error { + return termios.Tcsendbreak(uintptr(t.fd), 0) +} + +// SetDTR sets the DTR (data terminal ready) signal. +func (t *Term) SetDTR(v bool) error { + bits := unix.TIOCM_DTR + if v { + return termios.Tiocmbis(uintptr(t.fd), bits) + } else { + return termios.Tiocmbic(uintptr(t.fd), bits) + } +} + +// DTR returns the state of the DTR (data terminal ready) signal. +func (t *Term) DTR() (bool, error) { + status, err := termios.Tiocmget(uintptr(t.fd)) + return status&unix.TIOCM_DTR == unix.TIOCM_DTR, err +} + +// SetRTS sets the RTS (data terminal ready) signal. +func (t *Term) SetRTS(v bool) error { + bits := unix.TIOCM_RTS + if v { + return termios.Tiocmbis(uintptr(t.fd), bits) + } else { + return termios.Tiocmbic(uintptr(t.fd), bits) + } +} + +// RTS returns the state of the RTS (data terminal ready) signal. +func (t *Term) RTS() (bool, error) { + status, err := termios.Tiocmget(uintptr(t.fd)) + return status&unix.TIOCM_RTS == unix.TIOCM_RTS, err +} + +// Close closes the device and releases any associated resources. +func (t *Term) Close() error { + err := unix.Close(t.fd) + t.fd = -1 + return err +} diff --git a/vendor/github.com/pkg/term/term_solaris.go b/vendor/github.com/pkg/term/term_solaris.go new file mode 100644 index 0000000..d2d6462 --- /dev/null +++ b/vendor/github.com/pkg/term/term_solaris.go @@ -0,0 +1,165 @@ +package term + +// #include +import "C" + +import ( + "os" + "syscall" + "unsafe" + + "github.com/pkg/term/termios" + "golang.org/x/sys/unix" +) + +type attr unix.Termios + +func (a *attr) getSpeed() (int, error) { + // We generally only care about ospeed, since that's what would + // be used for padding characters, for example. + + rate := termios.Cfgetospeed((*syscall.Termios)(a)) + + switch rate { + case syscall.B50: + return 50, nil + case syscall.B75: + return 75, nil + case syscall.B110: + return 110, nil + case syscall.B134: + return 134, nil + case syscall.B150: + return 150, nil + case syscall.B200: + return 200, nil + case syscall.B300: + return 300, nil + case syscall.B600: + return 600, nil + case syscall.B1200: + return 1200, nil + case syscall.B1800: + return 1800, nil + case syscall.B2400: + return 2400, nil + case syscall.B4800: + return 4800, nil + case syscall.B9600: + return 9600, nil + case syscall.B19200: + return 19200, nil + case syscall.B38400: + return 38400, nil + case syscall.B57600: + return 57600, nil + case syscall.B115200: + return 115200, nil + case syscall.B230400: + return 230400, nil + case syscall.B460800: + return 460800, nil + case syscall.B500000: + return 500000, nil + case syscall.B576000: + return 576000, nil + case syscall.B921600: + return 921600, nil + default: + return 0, syscall.EINVAL + } +} + +func (a *attr) setSpeed(baud int) error { + var rate uint32 + switch baud { + case 50: + rate = unix.B50 + case 75: + rate = unix.B75 + case 110: + rate = unix.B110 + case 134: + rate = unix.B134 + case 150: + rate = unix.B150 + case 200: + rate = unix.B200 + case 300: + rate = unix.B300 + case 600: + rate = unix.B600 + case 1200: + rate = unix.B1200 + case 1800: + rate = unix.B1800 + case 2400: + rate = unix.B2400 + case 4800: + rate = unix.B4800 + case 9600: + rate = unix.B9600 + case 19200: + rate = unix.B19200 + case 38400: + rate = unix.B38400 + case 57600: + rate = unix.B57600 + case 115200: + rate = unix.B115200 + case 230400: + rate = unix.B230400 + case 460800: + rate = unix.B460800 + case 921600: + rate = unix.B921600 + default: + return unix.EINVAL + } + + err := termios.Cfsetispeed((*unix.Termios)(a), uintptr(rate)) + if err != nil { + return err + } + + err = termios.Cfsetospeed((*unix.Termios)(a), uintptr(rate)) + if err != nil { + return err + } + + return nil +} + +// Open opens an asynchronous communications port. +func Open(name string, options ...func(*Term) error) (*Term, error) { + fd, e := unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666) + if e != nil { + return nil, &os.PathError{"open", name, e} + } + + modules := [2]string{"ptem", "ldterm"} + for _, mod := range modules { + err := unix.IoctlSetInt(fd, C.I_PUSH, int(uintptr(unsafe.Pointer(unix.StringBytePtr(mod))))) + if err != nil { + return nil, err + } + } + + t := Term{name: name, fd: fd} + termios.Tcgetattr(uintptr(t.fd), &t.orig) + if err := termios.Tcgetattr(uintptr(t.fd), &t.orig); err != nil { + return nil, err + } + + if err := t.SetOption(options...); err != nil { + return nil, err + } + + return &t, unix.SetNonblock(t.fd, false) +} + +// Restore restores the state of the terminal captured at the point that +// the terminal was originally opened. +func (t *Term) Restore() error { + return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, &t.orig) +} diff --git a/vendor/github.com/pkg/term/term_windows.go b/vendor/github.com/pkg/term/term_windows.go new file mode 100644 index 0000000..d4fb4fa --- /dev/null +++ b/vendor/github.com/pkg/term/term_windows.go @@ -0,0 +1,114 @@ +package term + +import ( + "errors" +) + +type Term struct { +} + +var errNotSupported = errors.New("not supported") + +// Open opens an asynchronous communications port. +func Open(name string, options ...func(*Term) error) (*Term, error) { + return nil, errNotSupported +} + +// SetOption takes one or more option function and applies them in order to Term. +func (t *Term) SetOption(options ...func(*Term) error) error { + return errNotSupported +} + +// Read reads up to len(b) bytes from the terminal. It returns the number of +// bytes read and an error, if any. EOF is signaled by a zero count with +// err set to io.EOF. +func (t *Term) Read(b []byte) (int, error) { + return 0, errNotSupported +} + +// Write writes len(b) bytes to the terminal. It returns the number of bytes +// written and an error, if any. Write returns a non-nil error when n != +// len(b). +func (t *Term) Write(b []byte) (int, error) { + return 0, errNotSupported +} + +// Close closes the device and releases any associated resources. +func (t *Term) Close() error { + return errNotSupported +} + +// SetCbreak sets cbreak mode. +func (t *Term) SetCbreak() error { + return errNotSupported +} + +// CBreakMode places the terminal into cbreak mode. +func CBreakMode(t *Term) error { + return errNotSupported +} + +// SetRaw sets raw mode. +func (t *Term) SetRaw() error { + return errNotSupported +} + +// RawMode places the terminal into raw mode. +func RawMode(t *Term) error { + return errNotSupported +} + +// Speed sets the baud rate option for the terminal. +func Speed(baud int) func(*Term) error { + return func(*Term) error { return errNotSupported } +} + +// SetSpeed sets the receive and transmit baud rates. +func (t *Term) SetSpeed(baud int) error { + return errNotSupported +} + +// GetSpeed gets the transmit baud rate. +func (t *Term) GetSpeed() (int, error) { + var a attr + if err := termios.Tcgetattr(uintptr(t.fd), (*syscall.Termios)(&a)); err != nil { + return 0, err + } + return a.getSpeed() +} + +// Flush flushes both data received but not read, and data written but not transmitted. +func (t *Term) Flush() error { + return errNotSupported +} + +// SendBreak sends a break signal. +func (t *Term) SendBreak() error { + return errNotSupported +} + +// SetDTR sets the DTR (data terminal ready) signal. +func (t *Term) SetDTR(v bool) error { + return errNotSupported +} + +// DTR returns the state of the DTR (data terminal ready) signal. +func (t *Term) DTR() (bool, error) { + return false, errNotSupported +} + +// SetRTS sets the RTS (data terminal ready) signal. +func (t *Term) SetRTS(v bool) error { + return errNotSupported +} + +// RTS returns the state of the RTS (data terminal ready) signal. +func (t *Term) RTS() (bool, error) { + return false, errNotSupported +} + +// Restore restores the state of the terminal captured at the point that +// the terminal was originally opened. +func (t *Term) Restore() error { + return errNotSupported +} diff --git a/vendor/github.com/pkg/term/termios/doc.go b/vendor/github.com/pkg/term/termios/doc.go new file mode 100644 index 0000000..7b178c2 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/doc.go @@ -0,0 +1,4 @@ +// Package termios implements the low level termios(3) terminal line discipline facilities. +// +// For a higher level interface please use the github.com/pkg/term package. +package termios diff --git a/vendor/github.com/pkg/term/termios/ioctl.go b/vendor/github.com/pkg/term/termios/ioctl.go new file mode 100644 index 0000000..ce37d78 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/ioctl.go @@ -0,0 +1,16 @@ +// +build !windows,!solaris + +package termios + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +func ioctl(fd, request, argp uintptr) error { + if _, _, e := unix.Syscall6(syscall.SYS_IOCTL, fd, request, argp, 0, 0, 0); e != 0 { + return e + } + return nil +} diff --git a/vendor/github.com/pkg/term/termios/ioctl_darwin.go b/vendor/github.com/pkg/term/termios/ioctl_darwin.go new file mode 100644 index 0000000..5d9b91a --- /dev/null +++ b/vendor/github.com/pkg/term/termios/ioctl_darwin.go @@ -0,0 +1,10 @@ +package termios + +const ( + _IOC_PARAM_SHIFT = 13 + _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 +) + +func _IOC_PARM_LEN(ioctl uintptr) uintptr { + return (ioctl >> 16) & _IOC_PARAM_MASK +} diff --git a/vendor/github.com/pkg/term/termios/ioctl_solaris.go b/vendor/github.com/pkg/term/termios/ioctl_solaris.go new file mode 100644 index 0000000..95c40ea --- /dev/null +++ b/vendor/github.com/pkg/term/termios/ioctl_solaris.go @@ -0,0 +1,7 @@ +package termios + +import "golang.org/x/sys/unix" + +func ioctl(fd, request, argp uintptr) error { + return unix.IoctlSetInt(int(fd), uint(request), int(argp)) +} diff --git a/vendor/github.com/pkg/term/termios/pty.go b/vendor/github.com/pkg/term/termios/pty.go new file mode 100644 index 0000000..2f88d02 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty.go @@ -0,0 +1,48 @@ +// +build !windows + +package termios + +import ( + "fmt" + "os" + + "golang.org/x/sys/unix" +) + +func open_device(path string) (uintptr, error) { + fd, err := unix.Open(path, unix.O_NOCTTY|unix.O_RDWR|unix.O_CLOEXEC, 0666) + if err != nil { + return 0, fmt.Errorf("unable to open %q: %v", path, err) + } + return uintptr(fd), nil +} + +// Pty returns a UNIX 98 pseudoterminal device. +// Pty returns a pair of fds representing the master and slave pair. +func Pty() (*os.File, *os.File, error) { + ptm, err := open_pty_master() + if err != nil { + return nil, nil, err + } + + sname, err := Ptsname(ptm) + if err != nil { + return nil, nil, err + } + + err = grantpt(ptm) + if err != nil { + return nil, nil, err + } + + err = unlockpt(ptm) + if err != nil { + return nil, nil, err + } + + pts, err := open_device(sname) + if err != nil { + return nil, nil, err + } + return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil +} diff --git a/vendor/github.com/pkg/term/termios/pty_bsd.go b/vendor/github.com/pkg/term/termios/pty_bsd.go new file mode 100644 index 0000000..45336d4 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_bsd.go @@ -0,0 +1,37 @@ +// +build dragonfly openbsd + +package termios + +// #include +import "C" + +import "syscall" + +func open_pty_master() (uintptr, error) { + rc := C.posix_openpt(syscall.O_NOCTTY | syscall.O_RDWR) + if rc < 0 { + return 0, syscall.Errno(rc) + } + return uintptr(rc), nil +} + +func Ptsname(fd uintptr) (string, error) { + slavename := C.GoString(C.ptsname(C.int(fd))) + return slavename, nil +} + +func grantpt(fd uintptr) error { + rc := C.grantpt(C.int(fd)) + if rc == 0 { + return nil + } + return syscall.Errno(rc) +} + +func unlockpt(fd uintptr) error { + rc := C.unlockpt(C.int(fd)) + if rc == 0 { + return nil + } + return syscall.Errno(rc) +} diff --git a/vendor/github.com/pkg/term/termios/pty_darwin.go b/vendor/github.com/pkg/term/termios/pty_darwin.go new file mode 100644 index 0000000..9377112 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_darwin.go @@ -0,0 +1,36 @@ +package termios + +import ( + "errors" + "unsafe" + + "golang.org/x/sys/unix" +) + +func open_pty_master() (uintptr, error) { + return open_device("/dev/ptmx") +} + +func Ptsname(fd uintptr) (string, error) { + n := make([]byte, _IOC_PARM_LEN(unix.TIOCPTYGNAME)) + + err := ioctl(fd, unix.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) + if err != nil { + return "", err + } + + for i, c := range n { + if c == 0 { + return string(n[:i]), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} + +func grantpt(fd uintptr) error { + return unix.IoctlSetInt(int(fd), unix.TIOCPTYGRANT, 0) +} + +func unlockpt(fd uintptr) error { + return unix.IoctlSetInt(int(fd), unix.TIOCPTYUNLK, 0) +} diff --git a/vendor/github.com/pkg/term/termios/pty_freebsd.go b/vendor/github.com/pkg/term/termios/pty_freebsd.go new file mode 100644 index 0000000..d449fbf --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_freebsd.go @@ -0,0 +1,38 @@ +package termios + +import ( + "fmt" + "unsafe" +) + +func posix_openpt(oflag int) (fd uintptr, err error) { + // Copied from debian-golang-pty/pty_freebsd.go. + r0, _, e1 := unix.Syscall(unix.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) + fd = uintptr(r0) + if e1 != 0 { + err = e1 + } + return +} + +func open_pty_master() (uintptr, error) { + return posix_openpt(unix.O_NOCTTY | unix.O_RDWR | unix.O_CLOEXEC) +} + +func Ptsname(fd uintptr) (string, error) { + var n uintptr + err := ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return "", err + } + return fmt.Sprintf("/dev/pts/%d", n), nil +} + +func grantpt(fd uintptr) error { + var n uintptr + return ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) +} + +func unlockpt(fd uintptr) error { + return nil +} diff --git a/vendor/github.com/pkg/term/termios/pty_linux.go b/vendor/github.com/pkg/term/termios/pty_linux.go new file mode 100644 index 0000000..fc9954e --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_linux.go @@ -0,0 +1,31 @@ +package termios + +import ( + "fmt" + "unsafe" + + "golang.org/x/sys/unix" +) + +func open_pty_master() (uintptr, error) { + return open_device("/dev/ptmx") +} + +func Ptsname(fd uintptr) (string, error) { + var n uintptr + err := ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return "", err + } + return fmt.Sprintf("/dev/pts/%d", n), nil +} + +func grantpt(fd uintptr) error { + var n uintptr + return ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) +} + +func unlockpt(fd uintptr) error { + var n uintptr + return ioctl(fd, unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&n))) +} diff --git a/vendor/github.com/pkg/term/termios/pty_netbsd.go b/vendor/github.com/pkg/term/termios/pty_netbsd.go new file mode 100644 index 0000000..a40e7f9 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_netbsd.go @@ -0,0 +1,31 @@ +package termios + +import ( + "bytes" + + "golang.org/x/sys/unix" +) + +func open_pty_master() (uintptr, error) { + fd, err := unix.Open("/dev/ptmx", unix.O_NOCTTY|unix.O_RDWR, 0666) + if err != nil { + return 0, err + } + return uintptr(fd), nil +} + +func Ptsname(fd uintptr) (string, error) { + ptm, err := unix.IoctlGetPtmget(int(fd), unix.TIOCPTSNAME) + if err != nil { + return "", err + } + return string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)]), nil +} + +func grantpt(fd uintptr) error { + return unix.IoctlSetInt(int(fd), unix.TIOCGRANTPT, 0) +} + +func unlockpt(fd uintptr) error { + return nil +} diff --git a/vendor/github.com/pkg/term/termios/pty_solaris.go b/vendor/github.com/pkg/term/termios/pty_solaris.go new file mode 100644 index 0000000..6fccd1e --- /dev/null +++ b/vendor/github.com/pkg/term/termios/pty_solaris.go @@ -0,0 +1,33 @@ +package termios + +// #include +import "C" + +import "syscall" + +func open_pty_master() (uintptr, error) { + return open_device("/dev/ptmx") +} + +func Ptsname(fd uintptr) (string, error) { + slavename := C.GoString(C.ptsname(C.int(fd))) + return slavename, nil +} + +func grantpt(fd uintptr) error { + rc := C.grantpt(C.int(fd)) + if rc == 0 { + return nil + } else { + return syscall.Errno(rc) + } +} + +func unlockpt(fd uintptr) error { + rc := C.unlockpt(C.int(fd)) + if rc == 0 { + return nil + } else { + return syscall.Errno(rc) + } +} diff --git a/vendor/github.com/pkg/term/termios/termios.go b/vendor/github.com/pkg/term/termios/termios.go new file mode 100644 index 0000000..a69c1f0 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios.go @@ -0,0 +1,45 @@ +// +build !windows + +package termios + +import ( + "golang.org/x/sys/unix" +) + +// Tiocmget returns the state of the MODEM bits. +func Tiocmget(fd uintptr) (int, error) { + return unix.IoctlGetInt(int(fd), unix.TIOCMGET) +} + +// Tiocmset sets the state of the MODEM bits. +func Tiocmset(fd uintptr, status int) error { + return unix.IoctlSetInt(int(fd), unix.TIOCMSET, status) +} + +// Tiocmbis sets the indicated modem bits. +func Tiocmbis(fd uintptr, status int) error { + return unix.IoctlSetPointerInt(int(fd), unix.TIOCMBIS, status) +} + +// Tiocmbic clears the indicated modem bits. +func Tiocmbic(fd uintptr, status int) error { + return unix.IoctlSetPointerInt(int(fd), unix.TIOCMBIC, status) +} + +// Cfmakecbreak modifies attr for cbreak mode. +func Cfmakecbreak(attr *unix.Termios) { + attr.Lflag &^= unix.ECHO | unix.ICANON + attr.Cc[unix.VMIN] = 1 + attr.Cc[unix.VTIME] = 0 +} + +// Cfmakeraw modifies attr for raw mode. +func Cfmakeraw(attr *unix.Termios) { + attr.Iflag &^= unix.BRKINT | unix.ICRNL | unix.INPCK | unix.ISTRIP | unix.IXON + attr.Oflag &^= unix.OPOST + attr.Cflag &^= unix.CSIZE | unix.PARENB + attr.Cflag |= unix.CS8 + attr.Lflag &^= unix.ECHO | unix.ICANON | unix.IEXTEN | unix.ISIG + attr.Cc[unix.VMIN] = 1 + attr.Cc[unix.VTIME] = 0 +} diff --git a/vendor/github.com/pkg/term/termios/termios_bsd.go b/vendor/github.com/pkg/term/termios/termios_bsd.go new file mode 100644 index 0000000..f433f37 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_bsd.go @@ -0,0 +1,89 @@ +// +build darwin freebsd openbsd netbsd dragonfly + +package termios + +import ( + "time" + + "golang.org/x/sys/unix" +) + +const ( + FREAD = 0x0001 + FWRITE = 0x0002 + + IXON = 0x00000200 + IXOFF = 0x00000400 + IXANY = 0x00000800 + CCTS_OFLOW = 0x00010000 + CRTS_IFLOW = 0x00020000 + CRTSCTS = CCTS_OFLOW | CRTS_IFLOW +) + +// Tcgetattr gets the current serial port settings. +func Tcgetattr(fd uintptr, argp *unix.Termios) error { + return unix.IoctlSetTermios(int(fd), unix.TIOCGETA, argp) +} + +// Tcsetattr sets the current serial port settings. +func Tcsetattr(fd, opt uintptr, argp *unix.Termios) error { + switch opt { + case TCSANOW: + opt = unix.TIOCSETA + case TCSADRAIN: + opt = unix.TIOCSETAW + case TCSAFLUSH: + opt = unix.TIOCSETAF + default: + return unix.EINVAL + } + return unix.IoctlSetTermios(int(fd), uint(opt), argp) +} + +// Tcsendbreak function transmits a continuous stream of zero-valued bits for +// four-tenths of a second to the terminal referenced by fildes. The duration +// parameter is ignored in this implementation. +func Tcsendbreak(fd, duration uintptr) error { + if err := unix.IoctlSetInt(int(fd), unix.TIOCSBRK, 0); err != nil { + return err + } + time.Sleep(4 / 10 * time.Second) + return unix.IoctlSetInt(int(fd), unix.TIOCCBRK, 0) +} + +// Tcdrain waits until all output written to the terminal referenced by fd has been transmitted to the terminal. +func Tcdrain(fd uintptr) error { + return unix.IoctlSetInt(int(fd), unix.TIOCDRAIN, 0) +} + +// Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of which. +func Tcflush(fd, which uintptr) error { + var com int + switch which { + case unix.TCIFLUSH: + com = FREAD + case unix.TCOFLUSH: + com = FWRITE + case unix.TCIOFLUSH: + com = FREAD | FWRITE + default: + return unix.EINVAL + } + return unix.IoctlSetPointerInt(int(fd), unix.TIOCFLUSH, com) +} + +// Cfgetispeed returns the input baud rate stored in the termios structure. +func Cfgetispeed(attr *unix.Termios) uint32 { return uint32(attr.Ispeed) } + +// Cfgetospeed returns the output baud rate stored in the termios structure. +func Cfgetospeed(attr *unix.Termios) uint32 { return uint32(attr.Ospeed) } + +// Tiocinq returns the number of bytes in the input buffer. +func Tiocinq(fd uintptr) (int, error) { + return 0, nil +} + +// Tiocoutq return the number of bytes in the output buffer. +func Tiocoutq(fd uintptr) (int, error) { + return unix.IoctlGetInt(int(fd), unix.TIOCOUTQ) +} diff --git a/vendor/github.com/pkg/term/termios/termios_const.go b/vendor/github.com/pkg/term/termios/termios_const.go new file mode 100644 index 0000000..7e319bc --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_const.go @@ -0,0 +1,13 @@ +// +build !windows,!solaris + +package termios + +const ( + TCIFLUSH = 0 + TCOFLUSH = 1 + TCIOFLUSH = 2 + + TCSANOW = 0 + TCSADRAIN = 1 + TCSAFLUSH = 2 +) diff --git a/vendor/github.com/pkg/term/termios/termios_const_solaris.go b/vendor/github.com/pkg/term/termios/termios_const_solaris.go new file mode 100644 index 0000000..cd0f082 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_const_solaris.go @@ -0,0 +1,14 @@ +package termios + +// #include +import "C" + +const ( + TCIFLUSH = C.TCIFLUSH + TCOFLUSH = C.TCOFLUSH + TCIOFLUSH = C.TCIOFLUSH + + TCSANOW = C.TCSANOW + TCSADRAIN = C.TCSADRAIN + TCSAFLUSH = C.TCSAFLUSH +) diff --git a/vendor/github.com/pkg/term/termios/termios_linux.go b/vendor/github.com/pkg/term/termios/termios_linux.go new file mode 100644 index 0000000..9315fe4 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_linux.go @@ -0,0 +1,80 @@ +package termios + +import ( + "golang.org/x/sys/unix" +) + +const ( + TCSETS = 0x5402 + TCSETSW = 0x5403 + TCSETSF = 0x5404 + TCFLSH = 0x540B + TCSBRK = 0x5409 + TCSBRKP = 0x5425 + + IXON = 0x00000400 + IXANY = 0x00000800 + IXOFF = 0x00001000 + CRTSCTS = 0x80000000 +) + +// Tcgetattr gets the current serial port settings. +func Tcgetattr(fd uintptr, argp *unix.Termios) error { + return unix.IoctlSetTermios(int(fd), unix.TCGETS, argp) +} + +// Tcsetattr sets the current serial port settings. +func Tcsetattr(fd, action uintptr, argp *unix.Termios) error { + var request uintptr + switch action { + case TCSANOW: + request = TCSETS + case TCSADRAIN: + request = TCSETSW + case TCSAFLUSH: + request = TCSETSF + default: + return unix.EINVAL + } + return unix.IoctlSetTermios(int(fd), uint(request), argp) +} + +// Tcsendbreak transmits a continuous stream of zero-valued bits for a specific +// duration, if the terminal is using asynchronous serial data transmission. If +// duration is zero, it transmits zero-valued bits for at least 0.25 seconds, and not more that 0.5 seconds. +// If duration is not zero, it sends zero-valued bits for some +// implementation-defined length of time. +func Tcsendbreak(fd, duration uintptr) error { + return ioctl(fd, TCSBRKP, duration) +} + +// Tcdrain waits until all output written to the object referred to by fd has been transmitted. +func Tcdrain(fd uintptr) error { + // simulate drain with TCSADRAIN + var attr unix.Termios + if err := Tcgetattr(fd, &attr); err != nil { + return err + } + return Tcsetattr(fd, TCSADRAIN, &attr) +} + +// Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of selector. +func Tcflush(fd, selector uintptr) error { + return ioctl(fd, TCFLSH, selector) +} + +// Tiocinq returns the number of bytes in the input buffer. +func Tiocinq(fd uintptr) (int, error) { + return unix.IoctlGetInt(int(fd), unix.TIOCINQ) +} + +// Tiocoutq return the number of bytes in the output buffer. +func Tiocoutq(fd uintptr) (int, error) { + return unix.IoctlGetInt(int(fd), unix.TIOCOUTQ) +} + +// Cfgetispeed returns the input baud rate stored in the termios structure. +func Cfgetispeed(attr *unix.Termios) uint32 { return attr.Ispeed } + +// Cfgetospeed returns the output baud rate stored in the termios structure. +func Cfgetospeed(attr *unix.Termios) uint32 { return attr.Ospeed } diff --git a/vendor/github.com/pkg/term/termios/termios_solaris.go b/vendor/github.com/pkg/term/termios/termios_solaris.go new file mode 100644 index 0000000..cea79f1 --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_solaris.go @@ -0,0 +1,124 @@ +package termios + +// #include +// typedef struct termios termios_t; +import "C" + +import ( + "golang.org/x/sys/unix" + "unsafe" +) + +const ( + TCSETS = 0x5402 + TCSETSW = 0x5403 + TCSETSF = 0x5404 + TCFLSH = 0x540B + TCSBRK = 0x5409 + TCSBRKP = 0x5425 + + IXON = 0x00000400 + IXANY = 0x00000800 + IXOFF = 0x00001000 + CRTSCTS = 0x80000000 +) + +// See /usr/include/sys/termios.h +const FIORDCHK = C.FIORDCHK + +// Tcgetattr gets the current serial port settings. +func Tcgetattr(fd uintptr, argp *unix.Termios) error { + termios, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) + *argp = *(tiosTounix(termios)) + return err +} + +// Tcsetattr sets the current serial port settings. +func Tcsetattr(fd, action uintptr, argp *unix.Termios) error { + return unix.IoctlSetTermios(int(fd), uint(action), tiosToUnix(argp)) +} + +// Tcsendbreak transmits a continuous stream of zero-valued bits for a specific +// duration, if the terminal is using asynchronous serial data transmission. If +// duration is zero, it transmits zero-valued bits for at least 0.25 seconds, and not more that 0.5 seconds. +// If duration is not zero, it sends zero-valued bits for some +// implementation-defined length of time. +func Tcsendbreak(fd, duration uintptr) error { + return ioctl(fd, TCSBRKP, duration) +} + +// Tcdrain waits until all output written to the object referred to by fd has been transmitted. +func Tcdrain(fd uintptr) error { + // simulate drain with TCSADRAIN + var attr unix.Termios + if err := Tcgetattr(fd, &attr); err != nil { + return err + } + return Tcsetattr(fd, TCSADRAIN, &attr) +} + +// Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of selector. +func Tcflush(fd, selector uintptr) error { + return ioctl(fd, TCFLSH, selector) +} + +// Tiocinq returns the number of bytes in the input buffer. +func Tiocinq(fd uintptr, argp *int) (err error) { + *argp, err = unix.IoctlGetInt(int(fd), FIORDCHK) + return err +} + +// Tiocoutq return the number of bytes in the output buffer. +func Tiocoutq(fd uintptr, argp *int) error { + return ioctl(fd, unix.TIOCOUTQ, uintptr(unsafe.Pointer(argp))) +} + +// Cfgetispeed returns the input baud rate stored in the termios structure. +func Cfgetispeed(attr *unix.Termios) uint32 { + solTermios := tiosToUnix(attr) + return uint32(C.cfgetispeed((*C.termios_t)(unsafe.Pointer(solTermios)))) +} + +// Cfsetispeed sets the input baud rate stored in the termios structure. +func Cfsetispeed(attr *unix.Termios, speed uintptr) error { + solTermios := tiosToUnix(attr) + _, err := C.cfsetispeed((*C.termios_t)(unsafe.Pointer(solTermios)), C.speed_t(speed)) + return err +} + +// Cfgetospeed returns the output baud rate stored in the termios structure. +func Cfgetospeed(attr *unix.Termios) uint32 { + solTermios := tiosToUnix(attr) + return uint32(C.cfgetospeed((*C.termios_t)(unsafe.Pointer(solTermios)))) +} + +// Cfsetospeed sets the output baud rate stored in the termios structure. +func Cfsetospeed(attr *unix.Termios, speed uintptr) error { + solTermios := tiosToUnix(attr) + _, err := C.cfsetospeed((*C.termios_t)(unsafe.Pointer(solTermios)), C.speed_t(speed)) + return err +} + +// tiosToUnix copies a unix.Termios to a x/sys/unix.Termios. +// This is needed since type conversions between the two fail due to +// more recent x/sys/unix.Termios renaming the padding field. +func tiosToUnix(st *unix.Termios) *unix.Termios { + return &unix.Termios{ + Iflag: st.Iflag, + Oflag: st.Oflag, + Cflag: st.Cflag, + Lflag: st.Lflag, + Cc: st.Cc, + } +} + +// tiosTounix copies a x/sys/unix.Termios to a unix.Termios. +func tiosTounix(ut *unix.Termios) *unix.Termios { + return &unix.Termios{ + Iflag: ut.Iflag, + Oflag: ut.Oflag, + Cflag: ut.Cflag, + Lflag: ut.Lflag, + Cc: ut.Cc, + } +} diff --git a/vendor/github.com/pkg/term/termios/termios_windows.go b/vendor/github.com/pkg/term/termios/termios_windows.go new file mode 100644 index 0000000..884378c --- /dev/null +++ b/vendor/github.com/pkg/term/termios/termios_windows.go @@ -0,0 +1 @@ +package termios diff --git a/vendor/modules.txt b/vendor/modules.txt index b71a5c0..5ead9e6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -8,6 +8,9 @@ github.com/awnumar/memcall ## explicit; go 1.18 github.com/awnumar/memguard github.com/awnumar/memguard/core +# github.com/buger/goterm v1.0.4 +## explicit; go 1.15 +github.com/buger/goterm # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew @@ -83,6 +86,10 @@ github.com/lestrrat-go/option # github.com/muhlemmer/gu v0.3.1 ## explicit; go 1.18 github.com/muhlemmer/gu +# github.com/pkg/term v1.1.0 +## explicit; go 1.14 +github.com/pkg/term +github.com/pkg/term/termios # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib